本文介绍了基于 Accept 标头的 ASP.NET Core web api 操作选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想根据请求的接受标头为同一功能(实体列表)返回两种不同格式的响应,这是针对json"和html"请求的.

I want to return two different formatted responses for the same feature (a list of entities) based on the accept header of the request, it is for a "json" and a "html" request.

asp.net 核心是否支持根据请求中的接受标头为同一路由选择不同的操作?

Does the asp.net core support select different actions for the same route based upon the Accept Header from the request?

推荐答案

我深入研究了 .net 核心源代码并寻找了其他具有类似行为的属性,例如 Microsoft.AspNetCore.Mvc.HttpGetcode> 或 Microsoft.AspNetCore.Mvc.ProducesAttribute.这两个属性都实现了一个 Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraint 接口,aspnetcore.mvc 使用该接口来控制控制器内的动作选择.

I dived into the .net core source code and looked for other attributes that do some similar behaviour such as Microsoft.AspNetCore.Mvc.HttpGet or Microsoft.AspNetCore.Mvc.ProducesAttribute.Both attributes implements an Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraint interface wich is used by aspnetcore.mvc to control the selection of actions inside a controller.

所以我实现了一个简化的 ProducesAttribute(一个贡品")来检查接受标头.

So i implemented a simplified ProducesAttribute (a "tribute") to check for the accept header.

    /// <summary>
    /// A filter that specifies the supported response content types. The request accept header is used to determine if it is a valid action
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class AcceptHeaderAttribute : Attribute, IActionConstraint
    {

        public AcceptHeaderAttribute(string contentType, params string[] otherContentTypes)
        {
            if (contentType == null)
                throw new ArgumentNullException(nameof(contentType));

            // We want to ensure that the given provided content types are valid values, so
            // we validate them using the semantics of MediaTypeHeaderValue.
            MediaTypeHeaderValue.Parse(contentType);

            for (var i = 0; i < otherContentTypes.Length; i++)
            {
                MediaTypeHeaderValue.Parse(otherContentTypes[i]);
            }

            ContentTypes = GetContentTypes(contentType, otherContentTypes);
        }

        public MediaTypeCollection ContentTypes
        {
            get; set;
        }

        public int Order
        {
            get
            {
                return 0;
            }
        }

        private bool IsSubsetOfAnyContentType(string requestMediaType)
        {
            var parsedRequestMediaType = new MediaType(requestMediaType);
            for (var i = 0; i < ContentTypes.Count; i++)
            {
                var contentTypeMediaType = new MediaType(ContentTypes[i]);
                if (parsedRequestMediaType.IsSubsetOf(contentTypeMediaType))
                {
                    return true;
                }
            }
            return false;
        }

        public bool Accept(ActionConstraintContext context)
        {
            var requestAccept = context.RouteContext.HttpContext.Request.Headers[HeaderNames.Accept];
            if (StringValues.IsNullOrEmpty(requestAccept))
                return true;

            if (IsSubsetOfAnyContentType(requestAccept))
                return true;

            return false;
        }

        private MediaTypeCollection GetContentTypes(string firstArg, string[] args)
        {
            var completeArgs = new List<string>();
            completeArgs.Add(firstArg);
            completeArgs.AddRange(args);

            var contentTypes = new MediaTypeCollection();
            foreach (var arg in completeArgs)
            {
                contentTypes.Add(arg);
            }

            return contentTypes;
        }
    }

你可以用这个属性修饰任何动作.

You can decorate any action with this attribute.

请注意,它很容易更改并允许指定要检查的标题和值.

Note that it is easy to change and allow to specify the header you want to check and the value.

这篇关于基于 Accept 标头的 ASP.NET Core web api 操作选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 06:54