c# - 在 ASP.NET 5 中创建基于每个请求的 Controller /操作的格式化程序

标签 c# asp.net .net asp.net-core hateoas

我正在尝试在我的 ASP rest API 中实现 HATEOAS,更改 ReferenceResolverProvider

问题是,根据我使用的 Controller ,我想使用不同的 ReferenceResolvers,因为我需要对每个 Controller 采取不同的行为。

现在我有了通用选项:

services.AddMvc()
            .AddJsonOptions(option => option.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver())
            .AddJsonOptions(options => options.SerializerSettings.ReferenceResolverProvider = () => new RoomsReferenceResolver<Room>())
            .AddJsonOptions(options => options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects);

我想要这样的东西:

services.AddMvc()
            .AddJsonOptions(option => option.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver())
            .AddJsonOptions<RoomsController>(options => options.SerializerSettings.ReferenceResolverProvider = () => new RoomsReferenceResolver<Room>())
            .AddJsonOptions(options => options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects);

最佳答案

您似乎想要创建每个 Controller 特定的格式化程序。这可以通过使用名为 IResourceFilter 的过滤器来实现。一个简单的例子:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CamelCaseJsonFormatterResourceFilter : Attribute, IResourceFilter
{
    private readonly JsonSerializerSettings serializerSettings;

    public CamelCaseJsonFormatterResourceFilter()
    {
        // Since the contract resolver creates the json contract for the types it needs to deserialize/serialize,
        // cache it as its expensive
        serializerSettings = new JsonSerializerSettings()
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
    }

    public void OnResourceExecuted(ResourceExecutedContext context)
    {

    }

    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        // remove existing input formatter and add a new one
        var camelcaseInputFormatter = new JsonInputFormatter(serializerSettings);
        var inputFormatter = context.InputFormatters.FirstOrDefault(frmtr => frmtr is JsonInputFormatter);
        if (inputFormatter != null)
        {
            context.InputFormatters.Remove(inputFormatter);
        }
        context.InputFormatters.Add(camelcaseInputFormatter);

        // remove existing output formatter and add a new one
        var camelcaseOutputFormatter = new JsonOutputFormatter(serializerSettings);
        var outputFormatter = context.OutputFormatters.FirstOrDefault(frmtr => frmtr is JsonOutputFormatter);
        if (outputFormatter != null)
        {
            context.OutputFormatters.Remove(outputFormatter);
        }
        context.OutputFormatters.Add(camelcaseOutputFormatter);
    }
}

// Here I am using the filter to indicate that only the Index action should give back a camelCamse response
public class HomeController : Controller
{
    [CamelCaseJsonFormatterResourceFilter]
    public Person Index()
    {
        return new Person() { Id = 10, AddressInfo = "asdfsadfads" };
    }

    public Person Blah()
    {
        return new Person() { Id = 10, AddressInfo = "asdfsadfads" };
    }

如果您对过滤器的执行顺序感到好奇,下面是它们的顺序示例:

Inside TestAuthorizationFilter.OnAuthorization
Inside TestResourceFilter.OnResourceExecuting
Inside TestActionFilter.OnActionExecuting
Inside Home.Index
Inside TestActionFilter.OnActionExecuted
Inside TestResultFilter.OnResultExecuting
Inside TestResultFilter.OnResultExecuted
Inside TestResourceFilter.OnResourceExecuted

关于c# - 在 ASP.NET 5 中创建基于每个请求的 Controller /操作的格式化程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33455790/

相关文章:

c# - 新的 ScriptBundle .Include 不适用于 Breeze.min.js

c# - ASP.NET MVC Bootstrap Datepicker 日期验证问题

c# - 无法访问 Web 控件的 Page_Load 事件中的公共(public)方法

c# - 是否有警告(错误),类似于 C# 的 C4061

c# - 如何在输出之前修改整个 ASP.NET 页面内容?

c# - ASPX C# 页面超时

.net - 按 10 的幂缩放十进制值

.net - ODP.NET 可以重新分发吗?

C# 手动停止异步 for 语句(打字机效果)

C# 方法组奇怪