繁体   English   中英

如何在Asp.net MVC 5 ApiController中覆盖HttpGet / HttpPost

[英]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);
    }

}

DelegatingHandler的另一个示例

更多例子

我要做的不是创建覆盖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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM