zoukankan      html  css  js  c++  java
  • ASP.NET Web API编程——控制器

    1控制器操作的参数

    控制器操作的参数可以是内置类型也可以是自定义类型,无参也是允许的。

    还可以为控制器操作参数提供默认值。

    例:

    public IHttpActionResult User(int id=1)

            {

                return Json("id:"+id);

            }

    2控制器操作返回值

    类型

    说明

    void

    操作返回值为void时,Web API返回空HTTP响应,其状态码为204(无内容)

    HttpResponseMessage

    Web api会将此返回值直接转换为HTTP消息

    IHttpActionResult

    接口形式

    内置类型或自定义类型

     

    2.1返回值为HttpResponseMessage

    返回值为此类型时,有两种设置方式。

    第一种调用HttpResponseMessage的构造函数,实例化一个HttpResponseMessage,并返回。Web API会将其直接转换为HTTP消息。

    例:

            public HttpResponseMessage Get()
            {
                FileStream fs = new FileStream(@"D:GreatFile.txt",FileMode.Open);//文件流
                HttpResponseMessage hrm = new HttpResponseMessage
                {
                    StatusCode = HttpStatusCode.OK,
                    Content = new StreamContent(fs, 4096)
                };
    
                return hrm;
            }

    第二种方式是调用Request.CreateResponse方法,将自定义类型传递给它。Web API会调用序列化器将其序列化后写入HTTP响应。

            public HttpResponseMessage Get()
            {
                var publisher = new PublisherModel{Title ="ASP.NET Web API编程实战",Year=2018};
                return Request.CreateResponse<PublisherModel>(HttpStatusCode.OK, publisher);
            }

    HttpResponseMessage类的定义如下:

    public class HttpResponseMessage : IDisposable
    {
            public HttpResponseMessage();
            // 参数: statusCode:HTTP 响应的状态代码。
            public HttpResponseMessage(HttpStatusCode statusCode);
            // 获取或设置 HTTP 响应消息的内容。
            //返回 System.Net.Http.HttpContent。 HTTP 响应消息的内容。
            public HttpContent Content { get; set; }
            //获取 HTTP 响应标头的集合。
            public HttpResponseHeaders Headers { get; }
            //获取一个值,该值指示 HTTP 响应是否成功。
            //System.Net.Http.HttpResponseMessage.StatusCode。在 200-299 //范围中,则为 true;否则为 false。
            public bool IsSuccessStatusCode { get; }
            //获取或设置服务器与状态代码通常一起发送的原因短语。
            //返回 System.String。 服务器发送的原因词组。
            public string ReasonPhrase { get; set; }
            //获取或设置导致此响应消息的请求消息。
            public HttpRequestMessage RequestMessage { get; set; }
            //获取或设置 HTTP 响应的状态代码。
            public HttpStatusCode StatusCode { get; set; }
            //获取或设置 HTTP 消息版本。默认值为 1.1。
            public Version Version { get; set; }
            //释放由 System.Net.Http.HttpResponseMessage 使用的非托管资源,并可根据需要释放托管资源。
            //参数: 如果为 true,则释放托管资源和非托管资源;如果为 false,则仅释放非托管资源。
            protected virtual void Dispose(bool disposing);
            //如果 HTTP 响应的 System.Net.Http.HttpResponseMessage.IsSuccessStatusCode 属性//为 false,将引发异常。
            public HttpResponseMessage EnsureSuccessStatusCode();
            //返回表示当前对象的字符串。
            public override string ToString();
    }

    2.1.1设置响应状态:

    可以通过构造函数设置响应状态码,也可以通过StatusCode 属性设置响应状态码。

     

    2.1.2设置HTTP消息头

    通过HttpResponseMessage.Headers属性设置HTTP消息头,其类型为HttpResponseHeaders,下面是这个类型的定义:

    public sealed class HttpResponseHeaders : HttpHeaders
    {
            //获取 HTTP 请求的 Accept-Ranges 标头的值。
            public HttpHeaderValueCollection<string> AcceptRanges { get; }
            
            //获取或设置 HTTP 响应的 Age 标头值。
            public TimeSpan? Age { get; set; }        
            //获取或设置 HTTP 响应的 Cache-Control 标头值。
            public CacheControlHeaderValue CacheControl { get; set; }
            //获取 HTTP 请求的 Connection 标头的值。
            public HttpHeaderValueCollection<string> Connection { get; }
            //获取或设置指示 HTTP 响应的 Connection 标头是否应包含 Close 的值。
            public bool? ConnectionClose { get; set; }
            //获取或设置 HTTP 响应的 Date 标头值。
            public DateTimeOffset? Date { get; set; }
            //获取或设置 HTTP 响应的 ETag 标头值。
            public EntityTagHeaderValue ETag { get; set; }
            //获取或设置 HTTP 响应的 Location 标头值。
            public Uri Location { get; set; }
            //获取 HTTP 请求的 Pragma 标头的值。
            public HttpHeaderValueCollection<NameValueHeaderValue> Pragma { get; }
            //获取 HTTP 请求的 Proxy-Authenticate 标头的值。
            public HttpHeaderValueCollection<AuthenticationHeaderValue> ProxyAuthenticate { get; }
            //获取或设置 HTTP 响应的 Retry-After 标头值。
            public RetryConditionHeaderValue RetryAfter { get; set; }
            //获取 HTTP 请求的 Server 标头的值。
            public HttpHeaderValueCollection<ProductInfoHeaderValue> Server { get; }
            //获取 HTTP 请求的 Trailer 标头的值。
            public HttpHeaderValueCollection<string> Trailer { get; }
            //获取 HTTP 请求的 Transfer-Encoding 标头的值。
            public HttpHeaderValueCollection<TransferCodingHeaderValue> TransferEncoding { get; }
            //获取或设置指示 HTTP 响应的 Transfer-Encoding 标头是否应包含 chunked 的值。
            public bool? TransferEncodingChunked { get; set; }
            //获取 HTTP 请求的 Upgrade 标头的值。
            public HttpHeaderValueCollection<ProductHeaderValue> Upgrade { get; }
            //获取 HTTP 请求的 Vary 标头的值。
            public HttpHeaderValueCollection<string> Vary { get; }
            //获取 HTTP 请求的 Via 标头的值。
            public HttpHeaderValueCollection<ViaHeaderValue> Via { get; }
            //获取 HTTP 请求的 Warning 标头的值。
            public HttpHeaderValueCollection<WarningHeaderValue> Warning { get; }
            //获取 HTTP 请求的 WWW-Authenticate 标头的值。
            public HttpHeaderValueCollection<AuthenticationHeaderValue> WwwAuthenticate { get; }
    }

    对部分属性的解析

    1)可通过属性AcceptRanges来设置HTTP 请求的 Accept-Ranges 标头,当浏览器发现Accept-Range头时,可以尝试继续中断了的下载,而不是重新开始。设置为none表示不支持范围请求。设置为bytes表示支持范围请求。通过设置此表头,以支持断点续传机制。

    例:

                HttpResponseMessage hrm = new HttpResponseMessage
                {
                    //其他设置
                };
                hrm.Headers.AcceptRanges.Add("bytes");

    2)使用属性Location获取或设置重定向地址。

    浏览器收到此类响应时会跳转到指定的地址。

    例:

    public class ValuesController : ApiController
    {
            public HttpResponseMessage Get(int id)
            {
                HttpResponseMessage hrm = new HttpResponseMessage
                {
                    //其他设置
                };
                var controller = this.Request.GetRouteData().Values["controller"];
                var uri = new Uri(this.Url.Link("DefaultApi", new { controller = controller, id = id }));
                hrm.Headers.Location = uri;
                return hrm;
            }
    }

    2.1.3设置消息内容

    使用HttpResponseMessage.Content属性设置消息内容。

    HttpResponseMessage.Content属性的类型为HttpContent,其定义如下:

    public abstract class HttpContent : IDisposable
    {
         //其他代码略
    //根据 RFC 2616 中的定义,获取内容标头。 public HttpContentHeaders Headers { get; }
    //其他代码略 }

    HttpContent.Headers 属性

    其的定义如下:

    public sealed class HttpContentHeaders : HttpHeaders
    {
            //获取 HTTP 响应上的 Content-Disposition 内容标头值。
            public ContentDispositionHeaderValue ContentDisposition { get; set; }
            //获取 HTTP 响应的 Content-Encoding 内容标题的值。
            public ICollection<string> ContentEncoding { get; }
            //获取或设置 HTTP 响应上的 Content-Length 内容标头值。
            public long? ContentLength { get; set; }
            //获取或设置 HTTP 响应上的 Content-Range 内容标头值。
            public ContentRangeHeaderValue ContentRange { get; set; }
            //获取或设置 HTTP 响应上的 Content-Type 内容标头值。
            public MediaTypeHeaderValue ContentType { get; set; }
         //其他代码略
    }

    解析:

    1)Content-Disposition 内容标头值

    HTTP场景中,第一个参数或者是inline(默认值,表示回复中的消息体会以页面的一部分或者整个页面的形式展示),或者是attachment(意味着消息体应该被下载到本地;大多数浏览器会呈现一个“保存为”的对话框,将filename的值预填为下载后的文件名,假如它存在的话)。

    例:

    HttpResponseMessage response = new HttpResponseMessage() ;
    response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
    //设置文件名
    response.Content.Headers.ContentDisposition.FileName =”TextFile.txt”;

    2)Content-Length,指明发送给接收方的消息主体的大小

    例:

    HttpResponseMessage response = new HttpResponseMessage();
    response.Content.Headers.ContentLength = 32767;

     

    3)Content-Range,一个数据片段在整个文件中的位置

    例:

    HttpResponseMessage response = new HttpResponseMessage();
    new ContentRangeHeaderValue(0, 1024, 32767);

    4)Content-Type,用于指示资源的MIME类型

    例:

    HttpResponseMessage response = new HttpResponseMessage();
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

    根据实际的需要可以使用以下几种类型:StreamContentPushStreamContentByteArrayContentStringContent。

    使用StreamContent“拉”模式将数据放入响应

    例如:

    FileStream fileStream = new FileStream(@"D:	estfile.txt", FileMode.Open);
    HttpResponseMessage hrm = new HttpResponseMessage
    {
        //其他设置
    };
    hrm.Content = new StreamContent(fileStream, 1024);

    使用PushStreamContent“推”模式将数据放入响应。

    推模式的有点是,可以将数据一块一块地写入响应中,而不是一下子将数据先放入缓存中,然后全部发送出去。虽然StreamContent也可以,但只能将FileStream流赋给HttpResponseMessage.Content才能实现流传输,以达控制内存的目的,对于byte[]类型的数据就无能为力了。

    例如:

        public class DiskFileStream
        {
            private readonly string filename;
    
            public DiskFileStream(string filename)
            {
                this.filename = filename;
            }
    
            public async Task WriteToStream(Stream outputStream, HttpContent httpContent, TransportContext transportContext)
            {
                try
                {
                    var buffer = new byte[65536];
    
                    using (var file = File.Open(filename, FileMode.Open, FileAccess.Read))
                    {
                        var length = (int)file.Length;
                        var bytesRead = 1;
    
                        while (length > 0 && bytesRead > 0)
                        {
                            bytesRead = file.Read(buffer, 0, Math.Min(length, buffer.Length));
                            await outputStream.WriteAsync(buffer, 0, bytesRead);
                            length -= bytesRead;
                        }
                    }
                }
                catch (HttpException ex)
                {
                    return;
                }
                finally
                {
                    outputStream.Close();
                }
            }
        }
        
        //控制器
        public class DownLoadController:ApiController
        {
            public HttpResponseMessage Get(string filename)
            {
                var file = new DiskFileStream(filename);
    
                var response = Request.CreateResponse();
                Func<Stream, HttpContent, TransportContext,Task> onStreamAvailable = file.WriteToStream;
                response.Content = new PushStreamContent(onStreamAvailable, new MediaTypeHeaderValue("application/octet-stream"));
    
                return response;
            }
        }

    使用StringContent

    在基类控制器使用StringContent,以便返回Json类型的数据。如下定义了一个泛型方法,指定类型T为class。

    例如:

    public class BaseController : ApiController
    {
            public HttpResponseMessage ToJson<T>(T model) where T : class
            {
                string str = JsonConvert.SerializeObject(model);
                return new HttpResponseMessage { Content = new StringContent(str, Encoding.GetEncoding("UTF-8"), "application/json") };
            }
    }

    也可以不使用泛型方法,而对传入类型检测,但是需要做类型检查,不过可以序列化匿名类型。

            public HttpResponseMessage ToJson(Object obj)
            {
                String str = string.Empty;
                if (obj is String || obj is Char)
                {
                    str = obj.ToString();
                }
                else
                {
                    str = JsonConvert.SerializeObject(obj);
                }
                return new HttpResponseMessage { Content = new StringContent(str, Encoding.GetEncoding("UTF-8"), "application/json") };
            }

    2.1.4设置原因短语ReasonPhrase

    使用ReasonPhrase属性可以设置消息短语,用于解释状态码代表的含义。消息短语应尽可能地简洁扼要,尽量使用英文。

    例:

    HttpResponseMessage hrm = new HttpResponseMessage
    {
        StatusCode = (HttpStatusCode)701,
        ReasonPhrase = "Unable to find the user"
    
        //其他设置
    };

    2.2返回值为IHttpActionResult

    IHttpActionResult是一个接口,只有一个返回值为Task<System.Net.Http.HttpResponseMessage> 的异步方法ExecuteAsync。

    当控制器操作返回此类型时,Web API会调用ExecuteAsync方法创建类型为HttpResponseMessage的实例,然后将这个实例转换为HTTP消息。

    例:

    实现IHttpActionResult

    public class CustomActionResult : IHttpActionResult
    {
            private object param;
            private HttpRequestMessage request;
            public CustomActionResult(object param,HttpRequestMessage request)
            {
                this.param = param;
                this.request = request;
            }
            public System.Threading.Tasks.Task<HttpResponseMessage> ExecuteAsync(System.Threading.CancellationToken cancellationToken)
            {
                var response = new HttpResponseMessage
                {
                    Content = ......,
                    RequestMessage = ......
                };
            }
    }

    使用CustomActionResult 

            public IHttpActionResult GetOther()
            {
                object param = ......
                return CustomActionResult(param,Request);
            }

    注意;CustomActionResult 构造函数的参数为object类型,实际项目并不一定如此,这里只是举个例子而已。

    System.Web.Http.ApiController提供了几个方法返回值类型都继承自IHttpActionResult

    仅举几个常用的方法:

    protected internal JsonResult<T> Json<T>(T content);返回值JsonResult继承自IHttpActionResult,可将泛型参数T的实例序列化后写入HTTP响应中。

    protected internal virtual NotFoundResult NotFound();返回NotFoundResult,创建一个状态码为404的空响应。

    protected internal virtual OkResult Ok();返回值为OkResult ,创建一个状态码为200的空响应。

    protected internal virtual OkNegotiatedContentResult<T> Ok<T>(T content);返回值为OkNegotiatedContentResult,创建一个状态码为200的响应,并将参数content实例序列化写入响应消息体中。

    2.3返回值为内置类型或自定义类型

    返回值为内置类型或自定义类型时,Web API使用格式化器序列化返回值,并将其写入HTTP消息中,响应的状态码为200。

    例:

            public IEnumerable<string> Get()
            {
                return new string[] { "value1", "value2" };
            }

    3修饰控制器及操作

    使用特性修饰控制器及其操作。

    HTTP动词特性

    包括:HttpGet、HttpPost、HttpPut、HttpDelete,HttpHead,HttpPatch,HttpOptions只能用来修饰操作。

    HttpGet:使操作只能处理HTTP GET请求,用于获取资源且不对数据进行修改的操作。

    HttpPost:使操作只处理HTTP POST请求,用于传输数据实体或者对数据进行修改的操作。

    HttpPut:使操作只处理HTTP PUT请求,用于新增资源或者使用请求中的有效负载替换目标资源的表现形式。

    HttpDelete:使操作只处理HTTP DELETE请求,一般使用DELETE请求删除请求URL所指定的资源。

    HttpHead:使操作只处理HTTP HEADER请求,使用HEADER请求要求服务器的响应只返回首部,而不返回实体的主体部分。

    HttpPatch:使操作只处理HTTP PATCH请求,对资源执行部分修改。

    HttpOptions:使操作只处理HTTP OPTIONS请求,用于向服务器询问其支持的方法。

    PUT与POST方法的区别在于,PUT方法是幂等的:调用一次与连续调用多次是等价的(即没有副作用),而连续调用多次POST方法可能会有副作用,比如将一个订单重复提交多次。

    例:限定操作只支持post请求。

            [HttpPost]
            public IHttpActionResult ListALL()
            {
                //具体实现
                return Ok();
            }

    AcceptVerbs特性

    使用AcceptVerbs特性可设置允许多种HTTP方法调用,且支持非标准的HTTP方法。

    例:

    支持多种方法

            [AcceptVerbs("DELETE", "POST")]
            public void Delete(int id)
            {
            }

    支持自定义方法,这种方式比较少用,大多数情况下,HTTP标准方法足够用

            [AcceptVerbs("LALL")]
            public IHttpActionResult ListALL()
            {
                //具体实现
                return Ok();
            }

    Action重命名

    使用ActionName特性Action重命名。

    阻止方法被调用

    使用NonAction特性标记Action,阻止其被调用。

    使用路由特性

    使用RouteAttribute和RoutePrefix可以设置路由值。具体见路由一节。

    参考:

    1.https://docs.microsoft.com/en-us/aspnet/web-api/

    2.https://developer.mozilla.org/zh-CN/docs/Web

    转载与引用请注明出处。
    
    时间仓促,水平有限,如有不当之处,欢迎指正。
  • 相关阅读:
    由VMnet引起的browser-sync故障解决方案
    Gen8折腾日记
    实变函数笔记(1)——集合与基数
    密码学笔记(6)——复杂度及其相关内容
    微分几何笔记(1)——参数曲线、内积、外积
    密码学笔记(5)——Rabin密码体制和语义安全性
    密码学笔记(4)——RSA的其他攻击
    密码学笔记(2)——RSA密码
    密码学笔记(1)——数论准备知识
    第七章小结
  • 原文地址:https://www.cnblogs.com/hdwgxz/p/8711358.html
Copyright © 2011-2022 走看看