2012-08-31 9 views
5

Tengo el siguiente controlador de API:MVC Api Action & System.Web.Http.AuthorizeAttribute - ¿Cómo obtener los parámetros de la publicación?

public class TestController : ApiController 
{ 
    [HttpPost] 
    [APIAuthorizeAttribute] 
    public IQueryable<Computers> ListOfComputersInFolder(Guid folderId) 
    { 
     return GetListOfComputersForFolder(folderId); 
    } // End of ListOfComputersInFolder 
} // End of TestController 

Y la siguiente es mi APIAuthorizeAttribute básica.

public class APIAuthorizeAttribute : System.Web.Http.AuthorizeAttribute 
{ 
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext) 
    { 
     var Request = System.Web.HttpContext.Current.Request; 
     var folderId = Request.RequestContext.RouteData.Values["folderId"] ?? Request.Params["folderId] as string; 
     if(null == folderId) 
     { 
      folderId = actionContext.ControllerContext.RouteData.Values["folderId"]; 
     } 

     base.OnAuthorization(actionContext); 
    } 
} 

El problema que estoy teniendo es que folderId está saliendo nula en el método onAuthorize. (Basé el buscador en el código this).

Me parece que esto debería estar funcionando, pero parece que no puedo conseguirlo. ¿Alguna idea sobre lo que estoy haciendo mal y cómo debo obtener el parámetro publicado?

Editar: Traté de leer los datos enviados directamente con lo siguiente:

using (StreamReader inputStream = new StreamReader(request.InputStream)) 
{ 
    output = inputStream.ReadToEnd(); 
} 
request.InputStream.Position = 0; 

Lo que me pone los datos de correos en formato JSON que luego se pudo analizar, pero entonces mi llamada nunca lo hace sin embargo. Me da la siguiente excepción en la Respuesta:

<h2>500 - Internal server error.</h2> 
    <h3>There is a problem with the resource you are looking for, and it cannot be displayed. 

at System.Json.JXmlToJsonValueConverter.JXMLToJsonValue(Stream jsonStream, Byte[] jsonBytes)\u000d\u000a at System.Net.Http.Formatting.JsonMediaTypeFormatter.<>c__DisplayClass7.<OnReadFromStreamAsync>b__6()\u000d\u000a at System.Net.Http.Internal.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)"} 

EDIT: Al final, parece que esto podría ser un error con la combinación de ApiController, System.Web.Http.AuthorizeAttribute y HttpPost (que hace el trabajo cuando se utiliza HttpGet). Se ha enviado un informe de error.

Respuesta

7

El AuthorizeAttribute debe tener un parámetro AuthorizationContext en lugar de un HttpActionContext uno, desde que usted debería ser capaz de acceder al ejemplo RouteData

public override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    var folderId = filterContext.RouteData.Values["folderId"]; 
    ... 
} 

actualización

dado cuenta de que está utilizando ApiController y como tal utilizando Http.AuthorizeAttribute (explica por qué usted no tiene un AuthorizationContext). En ese caso, puede obtener el RouteData a través del contexto de acción, p. Ej.

var folderId = actionContext.Request.GetRouteData().Values["folderId"]; 
+3

Tenga en cuenta que debido a esto es un [APIController] (http://msdn.microsoft.com/en-us/library/system.web.http.apicontroller(v=vs.108).aspx) y no a [Controller] (http://msdn.microsoft.com /en-us/library/system.web.mvc.controller(v=vs.108) .aspx), utilizo 'System.Web.Http.AuthorizeAttribute' y no' System.Web.Mvc.AuthorizeAttribute'. Traté de acceder a su 'ControllerContext.RouteData.Values ​​[" folderId "] y todavía devolvió nulo. – Kyle

+0

@Zenox ver mi respuesta actualizada. – James

+0

gracias Eché un vistazo a esto también, pero aún no tuve suerte. La clase 'actionContext.Request' es un [HttpRequestMessage] (http://msdn.microsoft.com/en-us/library/system.net.http.httprequestmessage_methods) y no contiene un método' GetRouteData'. Además, si miro: actionContext.ControllerContext.RouteData.Values, solo contiene dos claves: controlador y acción. Creo que mi mejor opción de acción sería leer los datos de la entrada de inputStream. Lo intenté y confirmé que podía ver mis datos de publicación, pero parece un poco raro, así que voy a seguir buscando ahora. – Kyle

0

Usted puede dar a este método de extensión de un intento: (esto es un extracto del código de trabajo)

public static string GetParameter(this RequestContext requestContext, string key) 
{ 
    if (key == null) throw new ArgumentNullException("key"); 

    var lowKey = key.ToLower(); 

    return requestContext.RouteData.Values.ContainsKey(lowKey) && 
      requestContext.RouteData.Values[lowKey] != null 
       ? requestContext.RouteData.Values[lowKey].ToString() 
       : requestContext.HttpContext.Request.Params[lowKey]; 
} 

Estoy de acuerdo con la respuesta de James, que tiene que acceder al contexto de la petición a través de la ActionContext en este escenario

1

También he encontrado este problema.

Para evitar que me escribió el siguiente método que llamo desde dentro del método OnAuthorization:

private static object GetValueFromActionContext(HttpActionContext actionContext, string key) 
{ 
    var queryNameValuePairs = actionContext.Request.GetQueryNameValuePairs(); 

    var value = queryNameValuePairs 
     .Where(pair => pair.Key.Equals(key, StringComparison.OrdinalIgnoreCase)) 
     .Select(pair => pair.Value) 
     .FirstOrDefault(); 

    var methodInfo = ((ReflectedHttpActionDescriptor) (actionContext.ActionDescriptor)).MethodInfo; 
    var parameters = methodInfo.GetParameters(); 
    var parameterType = 
     parameters.Single(p => p.Name.Equals(key, StringComparison.OrdinalIgnoreCase)).ParameterType; 

    var converter = TypeDescriptor.GetConverter(parameterType); 

    return converter.ConvertFromString(value); 
} 

Este código hace las siguientes suposiciones:

  • La clave está extrayendo coincide con una nombre del argumento en el método de acción.

  • El tipo de parámetro que está obteniendo tendrá un convertidor válido para el tipo.

  • No está utilizando ningún enlace personalizado o formateo en el parámetro.

En el escenario que estoy usando el código sólo estoy esperando tipos simples como Guid, Boolean, cuerdas, etc y puede ser personalizado según sus necesidades.

El método de extensión GetQueryNameValuePairs es parte de la clase System.Net.Http.HttpRequestMessageExtensions y leerá los datos de la cadena/formulario.

Ejemplo del uso:

object folderId = GetValueFromActionContext(actionContext, "folderId"); 
0

Si contenttype de la solicitud es application/json;charset=utf-8

La acción API puede recuperar los datos del anuncio de la siguiente manera:

Stream stream = actionContext.Request.Content.ReadAsStreamAsync().Result; 
Encoding encoding = Encoding.UTF8; 
stream.Position = 0; 
string responseData = ""; 

using (StreamReader reader = new StreamReader(stream, encoding)) 
{ 
    responseData = reader.ReadToEnd().ToString(); 
} 

var dic = JsonConvert.DeserializeObject<IDictionary<string, string>>(responseData); 
Cuestiones relacionadas