ASP.NET MVC + RESTful服務之HttpStatusResult

來源:互聯網
上載者:User

開篇語與本主題無關,我非常尊敬的一個導師好幾天沒有見到人,今天聽說原來是病了,人也出現了。在此祝願他身體康健,長命百歲!

使用ASP.NET MVC構建RESTful服務時,想到一個問題:在使用POST,PUT,DELETE方法發送請求時伺服器端如何回傳響應?如果在操作過程中發生了異常情況,如何通知用戶端?

帶著這個問題,嘗試著構建了一個ActionResult的衍生類別:

namespace System.Web.Mvc{    public class HttpStatusResult : ActionResult    {        public HttpStatusResult()            : this(HttpStatusCode.OK)        {        }        public HttpStatusResult(HttpStatusCode statusCode)            : this(statusCode, "")        {        }        public HttpStatusResult(HttpStatusCode statusCode, string content)        {            this.StatusCode = statusCode;            this.Content = content;        }        public string Content { get; set; }        public HttpStatusCode StatusCode { get; set; }        public override void ExecuteResult(ControllerContext context)        {            context.HttpContext.Response.StatusCode = (int)StatusCode;            context.HttpContext.Response.ContentType = "text/xml, charset=\"utf-8\"";            if (string.IsNullOrEmpty(context.HttpContext.Request.Headers["Accept-Encoding"]) == false)            {                string acceptEncoding = context.HttpContext.Request.Headers["Accept-Encoding"].ToLower();                if (acceptEncoding.Contains("gzip"))                {                    context.HttpContext.Response.Filter = new GZipStream(context.HttpContext.Response.Filter, CompressionMode.Compress);                    context.HttpContext.Response.AppendHeader("Content-Encoding", "gzip");                }            }            using (var writer = XmlWriter.Create(context.HttpContext.Response.Output))            {                this.ResponseContent.WriteTo(writer);            }        }        private XmlDocument ResponseContent        {            get            {                XmlDocument xml = new XmlDocument();                xml.LoadXml(string.Format("<?xml version=\"1.0\"?><response xmlns=\"http://schema.cleversoft.com/webutil/httpstatusresult/1.0/\"><content>{0}</content></response>", this.Content));                return xml;            }        }    }}

使用這個類,可以向請求的用戶端返回一個Http Status資訊,如果操作正常,則視情況使用200,202,204。情況是什嗎?據HTTP/1.1定義:

POST:

The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result.

If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.

PUT:

If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.

DELETE:

A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not include an entity.

總而言之,看你真正做了什麼操作,返回一個與之匹配的HTTP Status Code。在此過程中也有可能遇到需要使用3XX系統的情況,不過我要做的服務中還沒有這麼複雜的規劃,據以前的學習發現,發現Google的服務中3XX用的比較多,整的比較複雜。

上面這些只僅僅是發送POST,PUT,DELETE成功的響應,如果僅是為了這個原因,似乎就沒有必要去做HttpStatusResult類型了。自已去實現RESTful服務,異常處理肯定是必須要考慮的內容。在我現在的設想中,如果一些操作發生了伺服器端的錯誤,那就得使用HttpStatusResult類型來向用戶端傳遞錯誤資訊,即HttpStatusResult.Content屬性。使用方法如下:

  return new HttpStatusResult(System.Net.HttpStatusCode.InternalServerError, "Exception Message.");  

在發送異常時我使用了InternalServerError(500)。

問題來了,使用了500以後,用戶端並不知道這是你“處心積慮”的發出來了,它只知道伺服器端出錯了,然後在WebRequest.GetResponse()時直接拋出異常了,而且沒有返回WebResponse,那我們使用Content返回的異常資訊豈不成了笑話了?所幸,M$也沒有這麼笨,大家可以仔細看下WebException的定義就會發現,原來使用WebException.Response就可以獲得剛才伺服器返回的響應,當然這時WebException.Status的狀態必須不能為ConnectFailure(值為2),這個Response屬性也必須不可為空(廢話),接下來,你就使用XmlReader從ResponseStream中拿資料吧,資料結構的定義可以視個人喜好定義:)。這裡比較推薦的方法是在響應的xml中定義一個NameSpace,為什麼nia?因為這樣你就可以確定這是你自已,而不是他人發來的響應。

最後,轉一下Http Status Code定義:

100 Continue

101 Switching Protocols

102 Processing

200 OK

201 Created

202 Accepted

203 Non-Authoritative Information

204 No Content

205 Reset Content

206 Partial Content

207 Multi-Status

226 IM Used

300 Multiple Choices

301 Moved Permanently

302 Found

303 See Other

304 Not Modified

305 Use Proxy

306 (Unused)

307 Temporary Redirect

400 Bad Request

401 Unauthorized

402 Payment Required

403 Forbidden

404 Not Found

405 Method Not Allowed

406 Not Acceptable

407 Proxy Authentication Required

408 Request Timeout

409 Conflict

410 Gone

411 Length Required

412 Precondition Failed

413 Request Entity Too Large

414 Request-URI Too Long

415 Unsupported Media Type

416 Requested Range Not Satisfiable

417 Expectation Failed

418 I'm a teapot

422 Unprocessable Entity

423 Locked

424 Failed Dependency

425 (Unordered Collection)

426 Upgrade Required

500 Internal Server Error

501 Not Implemented

502 Bad Gateway

503 Service Unavailable

504 Gateway Timeout

505 HTTP Version Not Supported

506 Variant Also Negotiates

507 Insufficient Storage

510 Not Extended

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.