【问题标题】:Model binding error with custom MediaTypeFormatter in ASP.Net Web APIASP.Net Web API 中自定义 MediaTypeFormatter 的模型绑定错误
【发布时间】:2012-03-20 17:28:56
【问题描述】:

我将JsonNetFormatter 找到here 与托管在ASP.Net MVC 4 beta 站点中的Web API beta 项目一起使用,并发现模型绑定的工作方式似乎与我使用默认JsonMediaTypeFormatter 时略有不同.切换到 JsonNetFormatter 模型绑定后似乎忽略了 URL 中设置的参数。例如,下面的代码在默认的JsonMediaTypeFormatter 下运行良好,但是当我使用JsonNetFormatter 时会抛出这个错误:

"The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Net.Http.HttpResponseMessage Put(Int32, WebAPISpike.Website.Api.Model.PutLesson)'...

JsonNetFormatter

public class JsonNetFormatter : MediaTypeFormatter
{
    private JsonSerializerSettings _jsonSerializerSettings;

    public JsonNetFormatter(JsonSerializerSettings jsonSerializerSettings)
    {
        _jsonSerializerSettings = jsonSerializerSettings ?? new JsonSerializerSettings();

        // Fill out the mediatype and encoding we support
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
        Encoding = new UTF8Encoding(false, true);
    }

    protected override bool CanReadType(Type type)
    {
        if (type == typeof(IKeyValueModel))
        {
            return false;
        }

        return true;
    }

    protected override bool CanWriteType(Type type)
    {
        return true;
    }

    protected override Task<object> OnReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext)
    {
        // Create a serializer
        JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);

        // Create task reading the content
        return Task.Factory.StartNew(() =>
        {
            using (StreamReader streamReader = new StreamReader(stream, Encoding))
            {
                using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader))
                {
                    return serializer.Deserialize(jsonTextReader, type);
                }
            }
        });
    }

    protected override Task OnWriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext, TransportContext transportContext)
    {
        // Create a serializer
        JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);

        // Create task writing the serialized content
        return Task.Factory.StartNew(() =>
        {
            using (StreamWriter streamWriter = new StreamWriter(stream, Encoding))
            {
                using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter))
                {
                    serializer.Serialize(jsonTextWriter, value);
                }
            }
        });
    }
}

Web API 配置

var serializerSettings = new JsonSerializerSettings();  
serializerSettings.Converters.Add(new IsoDateTimeConverter());

GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
GlobalConfiguration.Configuration.Formatters.Add(new JsonNetFormatter(serializerSettings));

控制器

public class LessonsController : ApiController {
    public HttpResponseMessage Put(int id, PutLesson updates) {
        // get lesson by id and update it with new values in from updates
        return new HttpResponseMessage(HttpStatusCode.OK);
    }
}

型号

public class PutLesson {
    public string LessonName { get; set; }
    public string Overview { get; set; }
}

我可以通过将 id 参数移动到我的 PutLesson 模型中然后将其设置在那里来解决此问题,但它不是标识资源的 URI,而是请求正文。 JsonNetFormatter 实现或我的配置中是否缺少某些内容?

【问题讨论】:

    标签: model-binding asp.net-mvc-4 asp.net-web-api


    【解决方案1】:

    这是 WebAPI 测试版中的一个错误(它发生在各种自定义 MediaTypeFormatter 中,计划在下一个版本中修复)。目前有两种解决方法可以解决此问题。最“干净”的似乎是添加一个 ActionFilter ,它将为您处理绑定这些参数。您可以在此处阅读更多信息:

    您还可以找到包含第二种解决方法的讨论链接。

    【讨论】:

      猜你喜欢
      • 2013-07-31
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      • 2018-12-11
      • 2012-08-28
      • 1970-01-01
      • 1970-01-01
      • 2019-05-10
      相关资源
      最近更新 更多