asp.net-mvc - 是否可以根据 Accept header 的媒体类型在 .NET MVC 中选择带有 AttributeRouting 的操作?

标签 asp.net-mvc asp.net-mvc-5 .net-4.5 attributerouting

我想根据 Accept header 中请求的媒体类型选择我的 Controller 的操作。

例如,我有一个名为主题的资源。其指定路线为:

GET /subjects/{subjectId:int}



正常情况下,浏览器请求的是text/html ,这很好。默认的 Media Formatter 处理得很好。

现在,当使用指定 application/pdf 的接受 header 访问同一路由时,我想要执行自定义逻辑。作为接受的媒体类型。

我可以创建一个自定义的媒体格式化程序,但是,据我所知,这意味着任何请求的路由都将 Accept header 设置为 application/pdf还将通过此媒体格式化程序运行。这是无法接受的。

在 Java 中,有一个名为 @Produces 的注解。 :

The @Produces annotation is used to specify the MIME media types or representations a resource can produce and send back to the client. If @Produces is applied at the class level, all the methods in a resource can produce the specified MIME types by default. If applied at the method level, the annotation overrides any @Produces annotations applied at the class level.



这将允许我执行以下操作:
namespace MyNamespace
{
    [RoutePrefix("subjects")]
    public class SubjectsController : Controller
    {
        [Route("{subjectId:int}")]
        [HttpGet]
        public ActionResult GetSubject(int subjectId)
        {
        }

        [Route("{subjectId:int}")]
        [HttpGet]
        [Produces("application/pdf")]
        public ActionResult GetSubjectAsPdf(int subjectId)
        {
            //Run my custom logic here to generate a PDF.
        }
    }
}

.NET 中没有我可以找到的 Produces 属性,当然,所以这不起作用。我也找不到类似的属性。

我当然可以手动检查 Action 主体内的标题,并将其重定向到另一个 Action ,但这充其量似乎是骇人听闻的。

.NET 4.5 中是否有一种机制可以用来解决我忽略或遗漏的问题?

(我正在使用 NuGet 存储库中的 MVC 5.2.2)

最佳答案

在 Internet 上搜索了一段时间后,我想到最好通过创建一个 ActionMethodSelectorAttribute 来实现这一点。 .

以下是 ProducesAttribute 的一个非常幼稚的第一遍实现我写的最终目的是模仿 Java 的 Produces 注释:

namespace YourNamespace
{
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Mime;
    using System.Web.Mvc;

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class ProducesAttribute : ActionMethodSelectorAttribute
    {
        private readonly ISet<ContentType> acceptableMimeTypes;

        public ProducesAttribute(params string[] acceptableMimeTypes)
        {
            this.acceptableMimeTypes = new HashSet<ContentType>();

            foreach (string acceptableMimeType in acceptableMimeTypes)
                this.acceptableMimeTypes.Add(new ContentType(acceptableMimeType));
        }

        public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
        {
            string acceptHeader = controllerContext.RequestContext.HttpContext.Request.Headers[HttpRequestHeader.Accept.ToString()];
            string[] headerMimeTypes = acceptHeader.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries);

            foreach (var headerMimeType in headerMimeTypes)
            {
                if (this.acceptableMimeTypes.Contains(new ContentType(headerMimeType)))
                    return true;
            }

            return false;
        }
    }
}

它旨在与属性路由一起使用,可以按如下方式应用:
public sealed class MyController : Controller
{
    [Route("subjects/{subjectId:int}")] //My route
    [Produces("application/pdf")]
    public ActionResult GetSubjectAsPdf(int subjectId)
    {
        //Here you would return the PDF representation.
    }

    [Route("subjects/{subjectId:int}")]
    public ActionResult GetSubject(int subjectId)
    {
        //Would handle all other routes.
    }
}

关于asp.net-mvc - 是否可以根据 Accept header 的媒体类型在 .NET MVC 中选择带有 AttributeRouting 的操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28573232/

相关文章:

c# - 不挂其他控件的WinForms验证

c# - .NET Core 但不是 .NET Framework 的 400 BadRequest 响应

javascript - 如何根据下拉菜单Asp MVC设置隐藏字段与显示字段相同

ASP.NET MVC - 如何将子站点 (ASP.NET) 添加到我的应用程序?

javascript - 选择 EditorFor MVC C# View 上的所有复选框

c# - MVC 5 - RedirectToAction 不重定向

c# - 在 .NET 4.5 中创建配置节处理程序错误时发生错误

C# - 身份框架和整数 UserId - 等待 SignInAsync 问题

asp.net-mvc - 哪个首先在 ASP.NET MVC、 Action 过滤器或 Controller 中实例化?

asp.net-mvc - Owin 如何在 Application_EndRequest 阶段之后设置 Asp.Net 身份验证 cookie?