国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

MVC4 WebAPI(二)——Web API工作方式

2019-11-17 01:53:46
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

MVC4 WebAPI(二)——Web API工作方式

在上篇文章中和大家一起學(xué)習(xí)了建立基本的WebAPI應(yīng)用,立刻就有人想到了一些問(wèn)題:1.客戶端和WebService之間文件傳輸2.客戶端或者服務(wù)端的安全控制要解決這些問(wèn)題,要了解一下WebAPI的基本工作方式。

(一)WebAPI中工作的Class

在MVC中大家都知道,獲取Request和Response使用HttPRequest和HttpResponse兩個(gè)類(lèi),在WebAPI中使用兩外兩個(gè)類(lèi):HttpRequestMessage 和HttpResponseMessage,分別用于封裝Requset和Response。除了這兩個(gè)類(lèi)之外,還有一個(gè)常見(jiàn)的抽象 類(lèi):HttpMessageHandler,用于過(guò)濾和加工HttpRequestMessage和HttpResponseMessage

(二)解決第一個(gè)問(wèn)題

其 實(shí)第一個(gè)問(wèn)題之所以被提出來(lái)應(yīng)該是和客戶端有關(guān),如果客戶端的請(qǐng)求是我們手寫(xiě)提交的,比如使用HttpClient封裝的請(qǐng)求,則要傳遞文件之前,我們一 般會(huì)進(jìn)行一次序列化,轉(zhuǎn)化為二進(jìn)制數(shù)組之類(lèi)的,在網(wǎng)絡(luò)上傳輸。這樣的話,在Controller中的Action參數(shù)里,我們只需要接收這個(gè)二進(jìn)制數(shù)組類(lèi) 型的對(duì)象就可以了。但是如果客戶端是Web Form呢,比如我們提交一個(gè)Form到指定的Controller的Action中,這個(gè)Action要接收什么類(lèi)型的參數(shù)呢?或者我們問(wèn)另外一個(gè)問(wèn)題,如果我將Web Form提交到一個(gè)WebAPI的Action中 ,我要怎么去取出這個(gè)表單中的數(shù)據(jù)呢?其 實(shí)我們應(yīng)該想到:我們的Action設(shè)置的參數(shù)之所以能夠被賦值,是因?yàn)閃ebAPI的架構(gòu)中在調(diào)用Action時(shí)將HTTP請(qǐng)求中的數(shù)據(jù)解析出來(lái)分別賦 值給Action中的參數(shù),如果真是這樣的話,我們只需要在Action中獲取到HTTP請(qǐng)求,然后直接獲取請(qǐng)求里面的數(shù)據(jù),就能解決上面的問(wèn)題。這 種想法是正確的,只不過(guò),此時(shí)的HTTP請(qǐng)求已經(jīng)不是最原始的HTTP Request,而是已經(jīng)被轉(zhuǎn)化成了HttpRequestMessage,在Action中,我們可以直接調(diào)用base.Requet來(lái)得到這個(gè) HttpRequestMessage實(shí)例,通過(guò)這個(gè)實(shí)例我們就可以隨心所欲的取出HTTP請(qǐng)求中想要的數(shù)據(jù)。

2.1從RequestMessage中獲取普通表單數(shù)據(jù)

這里的普通表單是指不包含F(xiàn)ile的表單,也就是說(shuō)表單的enctype值不是multipart/form-data,這時(shí),表單的數(shù)據(jù)默認(rèn)情況下是以Json來(lái)傳遞的如下頁(yè)面

復(fù)制代碼
<form name="form" action="~/api/FormSubmit?key=11234" method="post">    <input type="text" name="key" id="txtKey" />    <br />    <input type="text" name="value" id="txtValue" />    <br />        <input type="submit" id="btnSubmit" value="Submit" />     </form>
復(fù)制代碼

捕獲到的請(qǐng)求為

提交到對(duì)應(yīng)的Action為:

復(fù)制代碼
        [HttpPost]        public async void submitForm()        {            StringBuilder sb = new StringBuilder();            HttpContent content = Request.Content;            JsonObject jsonValue = await content.ReadAsOrDefaultAsync<JsonObject>();            foreach (var x in jsonValue)            {                sb.Append(x.Key);                string va ;                if (x.Value.TryReadAs<string>(out va))                {                    sb.Append(va);                }            }        }
復(fù)制代碼

這樣最后可以得到 Json的值:{"key":"123","value":"123"} sb處理后的值為:key123value123

注:在該action中使用到了關(guān)鍵字async和await,這些在4.5中新提出的關(guān)鍵字主要是用于進(jìn)行多線程取值的,在MVCAPI的設(shè)計(jì)中,大部分的方法都被設(shè)計(jì)成類(lèi)似于下面的方法

public static Task<T> ReadAsOrDefaultAsync<T>(this HttpContent content);

返 回值是一個(gè)Task,這種返回新線程的方法雖然可以提高系統(tǒng)的響應(yīng)能力,但是多線程取值會(huì)給編碼帶來(lái)不便,所以新出的關(guān)鍵字await用于阻塞當(dāng)前線程并 獲取目標(biāo)線程的返回值,在方法體中使用await關(guān)鍵字后要求將方法聲明為async用來(lái)表示該方法是異步的,并且返回值必須為void或者將返回者封裝 在一個(gè)Task中當(dāng)然,如果你不喜歡這種寫(xiě)法,上面的action也可以寫(xiě)為:

            Task readTask = content.ReadAsOrDefaultAsync<JsonObject>().ContinueWith((task) => { jsonValue = task.Result; });            readTask.Wait();

2.2從RequestMessage中獲取multipart表單數(shù)據(jù)將view頁(yè)面改寫(xiě)為

復(fù)制代碼
<form name="form" action="~/api/FormSubmit?key=11234" method="post" enctype="multipart/form-data" >    <input type="text" name="key" id="txtKey" />    <br />    <input type="text" name="value" id="txtValue" />    <br />    <input type="file" name="file" id="upFile" />    <br />    <input type="submit" id="btnSubmit" value="Submit" /></form>
復(fù)制代碼

此時(shí)捕獲到得請(qǐng)求是

這里的文件內(nèi)容被捕獲軟件解析成字符串,當(dāng)然如果我上傳的是其他的非文本格式的文件,文件會(huì)被轉(zhuǎn)化為二進(jìn)制數(shù)組這時(shí)如果我們不更改action,而直接調(diào)用,會(huì)發(fā)生錯(cuò)誤,原因很明顯,這個(gè)HTTP的報(bào)文內(nèi)容是無(wú)法被轉(zhuǎn)換為JSON的,這時(shí)我們需要將表單的報(bào)文解析成另外一種格式

復(fù)制代碼
                IEnumerable<HttpContent> bodyparts = await content.ReadAsMultipartAsync();                foreach (var bodypart in bodyparts)                {                    string name;                    name = bodypart.Headers.ContentDisposition.Name;                    sb.Append(name + ":");                    if (bodypart.Headers.Contains("filename"))                    {                        Stream stream = await bodypart.ReadAsStreamAsync();                        StreamReader reader = new StreamReader(stream);                        sb.Append(reader.ReadToEnd());                        sb.Append("----");                    }                    else                    {                        string val = await bodypart.ReadAsStringAsync();                        sb.Append(val);                        sb.Append("----");                    }                }
復(fù)制代碼

得到的處理后的sb值為:

{"key":123----"value":123----"file":******{文件的內(nèi)容}*****----}整合后的Action為

復(fù)制代碼
        [HttpPost]        public async void submitForm()        {            StringBuilder sb = new StringBuilder();            HttpContent content = Request.Content;            if (content.IsMimeMultipartContent())            {                IEnumerable<HttpContent> bodyparts = await content.ReadAsMultipartAsync();                foreach (var bodypart in bodyparts)                {                    string name;                    name = bodypart.Headers.ContentDisposition.Name;                    sb.Append(name + ":");                    if (bodypart.Headers.Contains("filename"))                    {                        Stream stream = await bodypart.ReadAsStreamAsync();                        StreamReader reader = new StreamReader(stream);                        sb.Append(reader.ReadToEnd());                        sb.Append("----");                    }                    else                    {                        string val = await bodypart.ReadAsStringAsync();                        sb.Append(val);                        sb.Append("----");                    }                }            }            else            {                JsonObject jsonValue = await content.ReadAsOrDefaultAsync<JsonObject>();                foreach (var x in jsonValue)                {                    sb.Append(x.Key);                    string va;                    if (x.Value.TryReadAs<string>(out va))                    {                        sb.Append(va);                    }                }            }        }
復(fù)制代碼

(三)WebAPI工作方式

要想解決第二個(gè)問(wèn)題就沒(méi)這么容易了,我們需要更深入的理解WebAPI的工作方式。其實(shí)對(duì)于WebAPI來(lái)說(shuō),它最初被設(shè)計(jì)為和WCF一樣的:客戶端、服務(wù)端兩套結(jié)構(gòu),我們到現(xiàn)在之所以還沒(méi)有提到客戶端,是因?yàn)槲覀兊恼?qǐng)求別的方式來(lái)封裝成HTTP請(qǐng)求或接收HTTP相應(yīng)的,比如Ajax和Form表單提交。在這里先給出一個(gè)服務(wù)端的響應(yīng)工作流,讓大家有個(gè)大體上的認(rèn)識(shí)aspDfAAAAAAAAcgPyGwAAAAAAQG5AfgMAAAAAAMgNyG8AAAAAAAC5AfkNAAAAAAAgNyC/AQAAAAAA5AbkNwAAAAAAgNyA/AYAAAAAAJAbkN8AAAAAAAByA/IbAAAAAABAbsij/BZJTOZGAAAAAAAA9iAv8lskEgmHw+FwOBQKBewz/tlepgL2mWAwGAqFwuFw8gzGPMu0EAqFAgvD241srDAtMI3I+boAAAAAACCvqDy/xUOX32XzNX5AXXned/U7/js/YMp39TveM1+nao4HHPPxFCdsIRKJhEKhYDBIDT+k7v7Ie+brvlsvxRuhLj5F3TxENf/B77IlagQAAAAAACB9qs1v8dwVoLa8ncW+q98N6i9GLJ30qplTtrFgdzF1+Tmq4ZTf6w6FQuwTcUz8CwaD1GgtdeX5QNXb4dGHtG2M10jY1BRsP0tdec7bcSFAbfEaAQAAAAAAkES257f4hYtCSTjspHf5PJve8p8Hmz6ILAzSq6YkFdRfpO78kFpfCgaDTOPRE3d+P9XwW3/lWxGLPnkLtG000Hzad+271OpsvBGZNxcAAAAAAKhYluY39vfNgj6P39xCNf/Bd/dH1N0f+e7+iNL+wW9uCWw5Rb+6tn3SbGPNd/vl0HDZDrkrVuGJGt/tI9750UAgEAwGmRa8d34Y1GtSbIFeNUUs+ngjiHAAAAAAACChbMxv22fPFsepsje8Z77uL3sj2H4mPFrJVLD9jL/sDercP1N3f+RbHI+f7IqnvmAw6HW7fLdfDhsb6BVj6hWZ0fluHtxanvZ6vZ5Np+/2y+HRyl21QK8YI9Ye/91XPXMjiHAAAAAAAGzaPhepcJG+AGtaSNPsIhWuoiXFepVDsiu/bV+1uDbnrXjL

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 滦南县| 三亚市| 靖西县| 安阳市| 调兵山市| 咸宁市| 五莲县| 基隆市| 明溪县| 邵阳县| 泸州市| 武汉市| 双牌县| 长垣县| 绩溪县| 镇远县| 乌鲁木齐县| 天水市| 灵丘县| 金川县| 江陵县| 南投县| 望谟县| 望奎县| 益阳市| 班戈县| 台北市| 松原市| 凤凰县| 洪雅县| 旬阳县| 兰坪| 汽车| 汕尾市| 阳西县| 石柱| 石台县| 许昌市| 布拖县| 麻栗坡县| 永登县|