序列化
ASP.NET 管道就是为此而设计的。您的控制器操作不会将结果返回给客户端,而是返回一个结果对象 ( ActionResult
),然后在 ASP.NET 管道中的进一步步骤中对其进行处理。您可以覆盖ActionResult
该类。请注意,FileResult, JsonResult, ContentResult
和FileContentResult
是 MVC3 中内置的。
在您的情况下,最好返回RestResult
对象之类的东西。该对象现在负责根据用户请求(或您可能拥有的任何其他规则)格式化数据:
public class RestResult<T> : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
string resultString = string.Empty;
string resultContentType = string.Empty;
var acceptTypes = context.RequestContext.HttpContext.Request.AcceptTypes;
if (acceptTypes == null)
{
resultString = SerializeToJsonFormatted();
resultContentType = "application/json";
}
else if (acceptTypes.Contains("application/xml") || acceptTypes.Contains("text/xml"))
{
resultString = SerializeToXml();
resultContentType = "text/xml";
}
context.RequestContext.HttpContext.Response.Write(resultString);
context.RequestContext.HttpContext.Response.ContentType = resultContentType;
}
}
反序列化
这有点棘手。我们在Deserialize<T>
基本控制器类上使用了一个方法。请注意,此代码不是生产就绪的,因为读取整个响应可能会溢出您的服务器:
protected T Deserialize<T>()
{
Request.InputStream.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(Request.InputStream);
var rawData = sr.ReadToEnd(); // DON'T DO THIS IN PROD!
string contentType = Request.ContentType;
// Content-Type can have the format: application/json; charset=utf-8
// Hence, we need to do some substringing:
int index = contentType.IndexOf(';');
if(index > 0)
contentType = contentType.Substring(0, index);
contentType = contentType.Trim();
// Now you can call your custom deserializers.
if (contentType == "application/json")
{
T result = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(rawData);
return result;
}
else if (contentType == "text/xml" || contentType == "application/xml")
{
throw new HttpException(501, "XML is not yet implemented!");
}
}