【问题标题】:Is it possible to change the MediaTypeFormatter to JSON for only one class?是否可以仅将一个类的 MediaTypeFormatter 更改为 JSON?
【发布时间】:2015-10-16 10:46:11
【问题描述】:

我有一个 web api,其中全局配置被配置为使用: XmlMediaTypeFormatter

我的问题是我不会用一个新的控制器来扩展这个 web api,而是使用 JsonMediaTypeFormatter。

是否可以仅将一个 API Controller 类的 MediaTypeFormatter 更改为 JSON?

我的问题是没有返回 JSON,我已经通过返回 HttpResponseMessage 来解决这个问题:

return new HttpResponseMessage
{
    Content = new ObjectContent<string>("Hello world", new JsonMediaTypeFormatter()),
    StatusCode = HttpStatusCode.OK
};

这是我得到问题的请求。如果我有一个具有两个属性的对象:

public class VMRegistrant 
{
    public int MerchantId { get; set; }
    public string Email { get; set; }
}

我的控制器操作将 VMRegistrant 作为参数:

public HttpResponseMessage CreateRegistrant(VMRegistrant registrant)
{
    // Save registrant in db...
}

但问题是当我使用 JSON 调用操作时它失败了。

【问题讨论】:

  • 是否在内容类型标头中包含“application/json”?
  • 是的,我确定,刚刚又做了一次检查。用提琴手检查。
  • 不确定这是否可行,但请尝试使用[FromBody] 属性。如果管道仅配置为 xml,则不确定它是否会起作用。

标签: c# asp.net-web-api


【解决方案1】:

您可以让您的控制器返回 IHttpActionResult 并使用扩展方法 HttpRequestMessageExtensions.CreateResponse&lt;T&gt; 并指定您要使用的格式化程序:

public IHttpActionResult Foo()
{
    var bar = new Bar { Message = "Hello" };
    return Request.CreateResponse(HttpStatusCode.OK, bar, new MediaTypeHeaderValue("application/json"));
}

另一种可能是使用ApiController.Content 方法:

public IHttpActionResult Foo()
{
    var bar = new Bar { Message = "Hello" };
    return Content(HttpStatusCode.OK, bar, new JsonMediaTypeFormatter(), new MediaTypeHeaderValue("application/json"));
}

编辑:

一种可能性是通过从流中读取并使用 JSON 解析器(例如 Json.NET)从 JSON 创建对象,自己从 Request 对象中读取和反序列化内容:

public async Task<IHttpActionResult> FooAsync()
{
      var json = await Request.Content.ReadAsStringAsync();
      var content = JsonConvert.DeserializeObject<VMRegistrant>(json);
}

【讨论】:

  • 是的,这就像一个魅力。但我的问题是请求的格式。我更新了我的问题以考虑到这一点。
  • @DNRN 查看我的编辑,了解获取内容的一种可能方式。
  • 感谢您的回复,我自己也在类似的轨道上:) 所以不可能使用视图模型作为参数,并以某种方式强制反序列化器使用 json。
  • @DNRN 我不知道。如果JsonFormatter 没有在Configuration 类中设置,我认为这是不可能的。
  • 我用空方法解决了,反序列化了内容:)
【解决方案2】:

是的,可以只为一个类/控制器更改MediaTypeFormatters。如果您想保存和恢复默认格式化程序,您可以按照以下步骤操作:

  • 在请求的开头保存旧的格式化程序
  • 清除格式化程序集合
  • 添加所需的格式化程序
  • 在请求结束时复制回旧的格式化程序

我认为ActionFilterAttribute 很容易做到这一点:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class ChangeFormatterAttribute : ActionFilterAttribute
{
    private IEnumerable<MediaTypeFormatter> oldFormatters;
    private MediaTypeFormatter desiredFormatter;

    public ChangeFormatterAttribute(Type formatterType)
    {
        this.desiredFormatter = Activator.CreateInstance(formatterType) as MediaTypeFormatter;
    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var formatters = actionContext.ControllerContext.Configuration.Formatters;

        oldFormatters = formatters.ToList();

        formatters.Clear();
        formatters.Add(desiredFormatter);

        base.OnActionExecuting(actionContext);
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        var formatters = actionExecutedContext.ActionContext.ControllerContext.Configuration.Formatters;

        formatters.Clear();
        formatters.AddRange(oldFormatters);

        base.OnActionExecuted(actionExecutedContext);
    }
}

及用法:

[ChangeFormatterAttribute(typeof(JsonMediaTypeFormatter))]
public class HomeController : ApiController
{
    public string Get()
    {
        return "ok";
    }
}

// ...

[ChangeFormatterAttribute(typeof(XmlMediaTypeFormatter))]
public class ValuesController : ApiController
{
    public string Get()
    {
        return "ok";
    }
}

【讨论】:

  • 我喜欢这个解决方案。是否可以对请求做类似的事情?我更新了我的问题以包含此内容。
  • 不确定这是否适用于异步请求模型。
【解决方案3】:

也许你可以让你的媒体类型格式化程序只接受你的控制器处理的类型:

public class Dog
{
    public string Name { get; set; }
}

public class DogMediaTypeFormatter : JsonMediaTypeFormatter
{
    public override bool CanReadType(Type type)
    {
        return type == typeof (Dog);
    }
}

虽然可能不是最好的解决方案:I

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    • 1970-01-01
    • 2012-05-03
    • 2019-12-02
    • 2017-01-04
    相关资源
    最近更新 更多