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

    转载与引用请注明出处。
    
    时间仓促,水平有限,如有不当之处,欢迎指正。
  • 相关阅读:
    sabaki and leelazero
    apply current folder view to all folders
    string operation in powershell
    wirte function in powershell
    add environment path to powershell
    Module in powershell
    sql prompt
    vmware中鼠标在部分区域不能使用
    调整多个控件的dock的顺序
    行为型模型 策略模式
  • 原文地址:https://www.cnblogs.com/hdwgxz/p/8711358.html
Copyright © 2011-2022 走看看