基于Accept标头的ASP.NET Core web api操作选择

时间:2017-05-24 11:08:44

标签: c# asp.net-core asp.net-core-mvc asp.net-core-webapi

我想基于请求的接受标头为同一个功能(实体列表)返回两个不同的格式化响应,它是针对" json"和一个" html"请求。

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

2 个答案:

答案 0 :(得分:12)

我深入了解了.net核心源代码,并寻找了其他类似行为的属性,例如Microsoft.AspNetCore.Mvc.HttpGetMicrosoft.AspNetCore.Mvc.ProducesAttribute。 这两个属性都实现了一个Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraint接口,由aspnetcore.mvc用来控制控制器内部动作的选择。

所以我实现了一个简化的ProducesAttribute("致敬")来检查接受标头。

    /// <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;
        }
    }

您可以使用此属性修饰任何操作。

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

答案 1 :(得分:2)

if(Request.Headers["Content-Type"] == "application/json")
{
    return OK(json);
}
else
{
    return View();
}

好吗?