我有以下Product
,CustomJsonMediaFormatter
和ProductsController
类:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}
public class CustomJsonMediaFormatter : BufferedMediaTypeFormatter
{
public CustomJsonMediaFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
}
public override bool CanWriteType(Type type)
{
if (type == typeof(Product))
{
return true;
}
else
{
Type enumerableType = typeof(IEnumerable<Product>);
return enumerableType.IsAssignableFrom(type);
}
}
public override bool CanReadType(Type type)
{
if (type == typeof(Product))
{
return true;
}
else
{
Type enumerableType = typeof(IEnumerable<Product>);
return enumerableType.IsAssignableFrom(type);
}
}
public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
using (var streamWriter = new StreamWriter(writeStream))
{
using (var jw = new JsonTextWriter(streamWriter))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(jw, value);
}
}
}
public override object ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
using (var streamReader = new StreamReader(readStream))
{
using (var jw = new JsonTextReader(streamReader))
{
JsonSerializer serializer = new JsonSerializer();
return serializer.Deserialize(jw);
}
}
}
}
public class ProductsController : ApiController
{
List<Product> products = new List<Product>
{
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
};
public IEnumerable<Product> GetAllProducts()
{
return products;
}
public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
public IHttpActionResult AddProduct([FromBody] Product product)
{
products.Add(product);
return Ok();
}
}
WebAPI设置如下所示:
config.MapHttpAttributeRoutes();
config.Formatters.Clear();
config.Formatters.Insert(0, new CustomJsonMediaFormatter());
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
问题:
HTTP请求GET http://localhost:47503/api/products/1
正常工作。正确调用CanWriteType(...)
和WriteToStream(...)
方法,另一端获得JSON产品。获取所有产品(GET http://localhost:47503/api/products
)也可以按预期工作。
但是,身体POST http://localhost:47503/api/products
的{{1}}不起作用。正确调用{"Id":10,"Name":"Apple","Category":"Groceries","Price":5.0}
和CanReadType(...)
方法。在ReadFromStream(...)
方法中正确生成了Product
类型的对象,但从不调用控制器中的ReadFromStream(...)
方法。然后使用type = AddProduct(...)
调用CanWriteType(...)
方法。
如果我使用默认的JSON格式化程序发出完全相同的请求,它可以正常工作。
内容类型是&#34; application / json&#34;在所有情况下。
谢谢, 尤利安
答案 0 :(得分:0)
必须告知路由选择用于POST请求的方法。该方法应该命名为Post
,或者您应该添加[HttpPost]
属性。
public IHttpActionResult Post([FromBody] Product product)
{
products.Add(product);
return Ok();
}
或
[HttpPost]
public IHttpActionResult AddProduct([FromBody] Product product)
{
products.Add(product);
return Ok();
}
答案 1 :(得分:0)
反序列化器不会生成Product对象,因此将反序列化结果转换为Product会产生错误。您可以使用反序列化来反序列化为正确的类型。
答案 2 :(得分:0)
您必须在Deserialize方法中指定Type。像这样:
using (StreamReader sw = new StreamReader(readStream))
{
var text = sw.ReadToEnd();
return JsonConvert.DeserializeObject(text, type);
}