我有以下API控制器:
public class TestController : ApiController
{
[HttpPost]
[APIAuthorizeAttribute]
public IQueryable<Computers> ListOfComputersInFolder(Guid folderId)
{
return GetListOfComputersForFolder(folderId);
} // End of ListOfComputersInFolder
} // End of TestController
以下是我的基本APIAuthorizeAttribute
。
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);
}
}
我遇到的问题是folderId
在onAuthorize方法中显示为null。 (我基于this代码的提取器。)
在我看来,这应该有效,但我似乎无法理解。关于我做错了什么以及如何获取发布参数的任何想法?
编辑:我尝试使用以下内容直接阅读帖子数据:
using (StreamReader inputStream = new StreamReader(request.InputStream))
{
output = inputStream.ReadToEnd();
}
request.InputStream.Position = 0;
这让我得到了JSON格式的帖子数据然后我可以解析,但是我的呼叫从未实现过。我在响应中得到以下异常:
<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)"}
编辑:
最后,似乎这可能是ApiController
,System.Web.Http.AuthorizeAttribute
和HttpPost
组合的错误(使用HttpGet
时确实有效)。已提交错误报告。
答案 0 :(得分:7)
AuthorizeAttribute应该有一个AuthorizationContext参数而不是HttpActionContext
个参数,您应该能够访问RouteData
,例如
public override void OnAuthorization(AuthorizationContext filterContext)
{
var folderId = filterContext.RouteData.Values["folderId"];
...
}
<强>更新强>
注意到您正在使用ApiController
,因此使用Http.AuthorizeAttribute
(解释了为什么您没有AuthorizationContext
)。在这种情况下,您可以通过操作上下文获取RouteData
,例如
var folderId = actionContext.Request.GetRouteData().Values["folderId"];
答案 1 :(得分:1)
我也遇到过这个问题。
为了解决这个问题,我编写了以下方法,我在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);
}
此代码做出以下假设:
您要提取的密钥与操作方法上的参数名称匹配。
您获得的参数类型将具有对该类型有效的转换器。
您没有在参数上使用任何自定义绑定或格式。
在我使用代码的场景中,我只期望Guid,Boolean,String等简单类型,并且可以根据您的要求进行自定义。
扩展方法GetQueryNameValuePairs是System.Net.Http.HttpRequestMessageExtensions类的一部分,将读取查询字符串/表单数据。
使用示例:
object folderId = GetValueFromActionContext(actionContext, "folderId");
答案 2 :(得分:0)
您可以尝试使用此扩展方法:(这是工作代码的摘录)
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];
}
我同意James的回答,您必须在此方案中通过actionContext访问请求上下文。
答案 3 :(得分:0)
如果请求的内容类型为application/json;charset=utf-8
API操作可以检索发布数据,如下所示:
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);