What are the best practices in adding custom heade

2019-08-24 04:28发布

问题:

I can see a lot of ways to do it online but most of them are messy, for me I was using these two ways

  • Using scopes, I did one for mobile and another one for the website

    var webScope = apiDescription.ActionDescriptor.GetFilterPipeline()
       .Select(filterInfo => filterInfo.Instance)
       .OfType<WebAuthorize>()
       .SelectMany(attr => attr.Roles.Split(','))
       .Distinct();
    
    var mobileScope = apiDescription.ActionDescriptor.GetFilterPipeline()
        .Select(filterInfo => filterInfo.Instance)
        .OfType<MobileAuthorize>()
       .SelectMany(attr => attr.Roles.Split(','))
       .Distinct();
    

    And it worked because I had two different ways in authorizing the api calls, as you can see I had a Mobile Authorize and a Web Authorize so my api calls would look something like this:

    [HttpGet]
    [Route("something")]
    [WebAuthorize(Code = PermissionCode, Type =PermissionType)]
    public async Task<Dto> Getsomething()
    {
        return await unitOfWork.GetService<ISomething>().GetSomething();
    }
    

    Issues I face when using scopes is that all calls that have web authorize will share the same headers so for the special calls I used another way to add custom headers.

  • Using apiDescription.RelativePath, and I will check it if the relative path is equal to the api call I want to add that custom header, example:

    [HttpPost]
    [Route("rename")]
    [InHouseAuthorize(Code = PermissionCode, Type =PermissionType)]
    public async Task<HttpResponseMessage> RenameDevice()
    {
        HttpRequestMessage request = Request ?? new HttpRequestMessage();
        String deviceName = request.Headers.GetValues("deviceName").FirstOrDefault();
        String deviceGuid = request.Headers.GetValues("deviceGuid").FirstOrDefault();
        await unitOfWork.GetService<IDeviceService>().RenameDevice(deviceGuid, deviceName);
        await unitOfWork.Commit();
        return new HttpResponseMessage(HttpStatusCode.OK);
    }
    

    And then I would add to the AddRequiredHeaderParameter.cs the following

        if (apiDescription.RelativePath.Contains("device/rename"))
        {
            operation.parameters.Add(new Parameter
            {
                name = "deviceGuid",
                @in = "header",
                description = "Add the Device Guid",
                type = "string",
                required = false
            });
            operation.parameters.Add(new Parameter
            {
                name = "DeviceName",
                @in = "header",
                description = "Add the Device Name",
                type = "string",
                required = false
            });
        }
    

    At first this was convenient and good enough fix but things are turning ugly as I'm adding a lot of calls that need custom headers and if the same URL have a Get and Post then it will even get uglier.

I am searching for the best way to deal with this issue.

回答1:

It's possible to use attribute [FromHeader] for web methods parameters (or properties in a Model class) which should be sent in custom headers. Something like this:

[HttpGet]
public ActionResult Products([FromHeader(Name = "User-Identity")]string userIdentity)

For me it looks like the easiest solution. At least it works fine for ASP.NET Core 2.1 and Swashbuckle.AspNetCore 2.5.0.