webvideo本地枚举文件太恶心了,算了写个服务器来读吧,顺便把avi和rmvb解包写了.
Controller
- 这里的Controller继承于ApiController,
- IE和Firefox发送了不同的Accept报头,导致返回的数据可以是JSON,也可以是XML(感觉太强大了,这都做好了。客户端请求的“application/json”中的Accept报头)
路由:/api/{controller}/{id}
在id = RouteParameter.Optional
情况下
controller匹配控制器名
{id} 匹配名称为id的方法参数(即函数的参数名叫id)
/api/products
products
匹配名为ProductsController的控制器。该请求是一个GET请求,因此框架在ProductsController上查找一个名称以GET…
开头的方法。
进一步地,这个URI不包含可选的{id}片段,因此,框架查找的是一个不带参数的方法。于是,ProductsController::GetAllProducts满足所有这些需求
同理 如果是个POST``Put
请求,会去找POST``Put
开头的方法 以及Delete
/api/products/1
找到参数名叫id的函数,并把这个传入。
同理 /api/products/abc
就不行,因为只有GetProductById有个叫id的参数,但是是int,无法转换为string
Post
js和c#的完美兼容,直接互相传对象,完全可以解析
WebapiClient
添加库,用HttpClient
设置base uri,设置请求报头。
上面讲了client.GetAsync("api/products").Result
是阻塞函数,并不会把控制返回给调用者,这导致一直阻塞(ui线程阻塞)。
给出2个解决方法:
async
和await
12345678910111213141516171819202122232425262728private async void GetProducts(object sender, RoutedEventArgs e){try{btnGetProducts.IsEnabled = false;var response = await client.GetAsync("api/products");response.EnsureSuccessStatusCode(); // Throw on error code(有错误码时报出异常).var products = await response.Content.ReadAsAsync<IEnumerable<Product>>();_products.CopyFrom(products);}catch (Newtonsoft.Json.JsonException jEx){// This exception indicates a problem deserializing the request body.// 这个异常指明了一个解序列化请求体的问题。MessageBox.Show(jEx.Message);}catch (HttpRequestException ex){MessageBox.Show(ex.Message);}finally{btnGetProducts.IsEnabled = true;}}安装
Async Targeting Pack
123456789101112131415161718192021222324252627282930client.GetAsync("api/products/2").ContinueWith((t) =>{if (t.IsFaulted){MessageBox.Show(t.Exception.Message);btnGetProducts.IsEnabled = true;}else{var response = t.Result;if (response.IsSuccessStatusCode){response.Content.ReadAsAsync<IEnumerable<Product>>().ContinueWith(t2 =>{if (t2.IsFaulted){MessageBox.Show(t2.Exception.Message);btnGetProducts.IsEnabled = true;}else{var products = t2.Result;_products.CopyFrom(products);btnGetProducts.IsEnabled = true;}}, TaskScheduler.FromCurrentSynchronizationContext());}}}, TaskScheduler.FromCurrentSynchronizationContext());
HttpClient消息处理器
通过这个我可以把自定义的头处理掉
路由变异
id = RouteParameter.Optional
情况下
当路由为 api/{controller}/{action}/{id}
时,
### 异常处理
总而言之(exception和error都用最好):
自定义消息过滤
这个要继承DelegatingHandler
,服务器在config.MessageHandlers加,客户端在HttpClient加。
唯一的注意http头的加法,客户端随便加,服务器一般如此
Post数据
有俩种,复合类型和简单类型
- 复合类型(传和接受都是自定义的结构体)
服务器对对这类型没啥要求,传入参数是自定义类或结构体就好。
客户端代码必须传application/json
格式数据(我用postman测试了下,选raw,传json字符串可以的)
|
|
- 简单类型(服务器接收的是string int这种类型)
服务器要求用[FromBody]
修饰参数
客户端要求发送=value
的数据(代码和测试真心发俩种数据)
客户端代码,不知道为何必须用{ "": ["update one", "update two", "update three"] }
格式数据 且x-www-form-urlencoded
它才认同
ajax只需要传上面的格式就好了
然而我用postman
选raw
,传=rety
就可以传入rety
字符进去。
angular的js没试过,放以后把
Upload Form Data
|
|
限制数据
如下对结构进行限制
Under-Posting和Over-Posting
Under-Posting
当客户端提交时遗漏某些属性,json格式化器会默认给缺失赋值(0)Over-Posting
当客户端提交时属性过多时,格式化器会忽略多余的属性
NuGet和Self-Host
Microsoft.AspNet.WebApi.OwinSelfHost
是自驻留服务安装的- controller接口一定要
public
,这个搞了我好久哦。
单个webapi自己的话(weapi.core
是必须的),要加Microsoft.AspNet.WebApi.WebHost
这个模式下直接用Global.asax
做入口是可以的.(遇见403不怕,只是页面没添加,api接口还是好的)
后来翻资料,还有其它方法可以用Microsoft.Owin.Host.SystemWeb and Microsoft.AspNet.WebApi.Owin
;建立Startup
入口是可以的。
(完全想不明白,为何俩台电脑反应如此不同)
self的要加Microsoft.AspNet.WebApi.OwinSelfHost
(这个官方介绍是有俩种方式的,我个人喜欢用owin)xcopy /y "$(TargetDir)$(ProjectName).*" "$(ProjectDir)\..\WebHostServerC\bin\Debug"
content root和web root
要用content root要安装Microsoft.AspNetCore.StaticFiles
(Microsoft.AspNetCore.Hosting
里面有PhysicalFileProviderd的类)
路由属性和重定向
一直看他们用Route
和RoutePrefix
来指定路由,发现调用 MapHttpAttributeRoutes
就可以使用了。
路由属性的好处是,可以使用匹配路由([Route(“~/api/authors/{authorId:int}/books”)]public IEnumerable
先把重定向代码贴了。
静态资源访问
Microsoft.Owin.StaticFiles
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files