[英]How to override HttpGet/HttpPost in Asp.net MVC 5 ApiController
我想重写API控制器,以检查所有HttpGet和HttpPost调用的标头中是否包含某些值,而不必在每个调用中都包含检查代码。 目前,我的方法如下:
public class MyApiController : ApiController
{
[HttpGet]
public HttpResponseMessage GetAccountById()
{
var accountId = (Request.Headers.Where(t => t.Key == "accountid").Count() == 0) ? null : Request.Headers.GetValues("accountid").First();
var apiKey = (Request.Headers.Where(t => t.Key == "apikey").Count() == 0) ? null : Request.Headers.GetValues("apikey").First();
if (String.IsNullOrEmpty(accountId)) {
return Request.CreateResponse(HttpStatusCode.Forbidden, "Please provide an Account Id.");
}
if (String.IsNullOrEmpty(apiKey)) {
return Request.CreateResponse(HttpStatusCode.Forbidden, "Please provide an Account Api Key.");
}
// Get Account
// return Account;
}
}
如何在每个调用中执行apikey / accountid校验,而不必将校验写入每个调用中?
解决方案:重写DelegatingHandler可以正常工作。
ApiSecurityHandler.cs
public class ApiSecurityHandler : DelegatingHandler
{
public ApiSecurityHandler(HttpConfiguration httpConfiguration)
{
InnerHandler = new HttpControllerDispatcher(httpConfiguration);
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var accountId = (request.Headers.Where(t => t.Key == "accountid").Count() == 0) ? null : request.Headers.GetValues("accountid").First();
var apiKey = (request.Headers.Where(t => t.Key == "apikey").Count() == 0) ? null : request.Headers.GetValues("apikey").First();
if (String.IsNullOrEmpty(accountId)) {
var response = new HttpResponseMessage(HttpStatusCode.Forbidden);
response.Content = new StringContent("Please provide an Account Id.");
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response);
return tsc.Task;
}
if (String.IsNullOrEmpty(apiKey)) {
var response = new HttpResponseMessage(HttpStatusCode.Forbidden);
response.Content = new StringContent("Please provide an Account Api Key.");
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response);
return tsc.Task;
}
// Authorize the Account Id and Api Key here
using (var accountManager = new AccountManager()) {
if (!accountManager.AuthorizeAccountApiKey(accountId, apiKey)) {
var response = new HttpResponseMessage(HttpStatusCode.Forbidden);
response.Content = new StringContent("Api authorization denied.");
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response);
return tsc.Task;
}
}
return base.SendAsync(request, cancellationToken);
}
}
在您的路由配置中,只需将此参数添加到地图路线即可:
handler: new ApiSecurityHandler(GlobalConfiguration.Configuration)
使用自己的OnAuthorization
实现编写System.Web.Http.Filters.AuthorizationFilterAttribute
的子类,然后可以在单个控制器方法或控制器本身上使用此属性。
我建议使用DelegatingHandler。
msdn的此示例显示了如何覆盖标题
这段代码应该工作,享受:
public class Myhandler: DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessagerequest, CancellationToken cancellationToken)
{
if(request.Headers.Contains("accountid") && request.Headers.Contains("apikey"))
{
string accountid = request.Headers.GetValues("accountid").FirstOrDefault();
string apikey = request.Headers.GetValues("apikey").FirstOrDefault();
//HERE you can get your account and do what you want
}else{
return SendError("please provide account id and api key", HttpStatusCode.Forbidden);
}
return base.SendAsync(request, cancellationToken);
}
private Task<HttpResponseMessage> SendError(string error, HttpStatusCode code)
{
var response = new HttpResponseMessage();
response.Content = new StringContent(error);
response.StatusCode = code;
return Task<HttpResponseMessage>.Factory.StartNew(() => response);
}
}
我要做的不是创建覆盖ApiController的方法,而是创建一个继承ApiController的基类,并在那里进行编码。 像这样:
public class APIBaseController : ApiController
{
[HttpGet]
public void APIBaseController() {
//Request.Headers.Count()
}
[HttpPost]
public void APIBaseController() {
//Request.Headers.Count()
}
}
然后执行以下操作:
public class MyApiController : APIBaseController
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.