是否可以仅将MediaTypeFormatter更改为JSON?

时间:2015-10-16 10:46:11

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

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

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

是否可以仅为一个API控制器类将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调用该操作时,它失败了。

3 个答案:

答案 0 :(得分:3)

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

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"));
}

修改

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

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

答案 1 :(得分:1)

是的,可以仅为一个类/控制器更改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";
    }
}

答案 2 :(得分:0)

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

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

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

可能不是最好的解决方案:我