7

我正在 ASP.NET MVC 中创建一个 REST API。我希望请求和响应的格式是 JSON 或 XML,但是我也想让添加另一种数据格式变得容易,并且容易先创建 XML,然后再添加 JSON。

基本上我想指定我的 API GET/POST/PUT/DELETE 请求的所有内部工作,而不必考虑数据以什么格式进入或它将以什么格式离开,我可以在以后轻松指定格式或更改它每个客户。所以一个人可以使用 JSON,一个人可以使用 XML,一个人可以使用 XHTML。后来我也可以添加另一种格式,而不必重写大量代码。

我不想在所有操作的末尾添加一堆 if/then 语句并确定数据格式,我猜有某种方法可以使用接口或继承等来做到这一点,只是不确定最好的方法。

4

2 回答 2

7

序列化

ASP.NET 管道就是为此而设计的。您的控制器操作不会将结果返回给客户端,而是返回一个结果对象 ( ActionResult),然后在 ASP.NET 管道中的进一步步骤中对其进行处理。您可以覆盖ActionResult该类。请注意,FileResult, JsonResult, ContentResultFileContentResult是 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!");
    }
}
于 2011-06-08T14:59:46.980 回答
0

只是想把它放在这里以供参考,但我发现使用 ASP.NET MVC 可能不是最好的方法:

Windows Communication Foundation (WCF) 提供了一个统一的编程模型,用于快速构建跨 Web 和企业通信的面向服务的应用程序

当今的 Web 应用程序开发人员面临着如何公开数据和服务的新挑战。云、移动到设备以及转向基于浏览器的框架(如 jQuery)都对以 Web 友好的方式呈现此类功能提出了越来越高的要求。WCF 的 Web API 产品专注于为开发人员提供工具来编写在这个新世界中运行的简单而强大的应用程序。对于想要进一步超越 HTTP 公开的开发人员,我们的 API 将允许您访问 HTTP 的所有丰富性并在应用程序开发中应用 RESTful 约束。这项工作是 .Net 4.0 中已经提供的 HTTP/ASP.NET AJAX 功能的演变。

http://wcf.codeplex.com/

但是,我不会选择这个作为答案,因为尽管这是我要走的路线,但它实际上并没有回答这个问题。我只是想把它放在这里对未来的研究人员有所帮助。

于 2011-06-08T17:28:51.453 回答