シリアル化
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!");
}
}