今天咱们来实现一个特殊的需求,这个需求说来也不过度,不过有点违背WebAPi的真实用途,WebAPi不过是做为传输数据而用,若非在项目开发中断不可想到还要实现一个页面来实时显示列表并进行后续其余操做。接下来咱们来看看。javascript
当咱们创建一个应用程序时能够选择是否创建WebAPi项目,咱们选择创建WebAPi,同时在其根目录下创建一个Index的Html页面,因而乎则有了以下的样子:html
咱们运行起来看看是否能正确显示结果:java
从这里咱们能够看出貌似不存在咱们本节所须要讲解的问题,这里的介绍也就仅供咱们玩玩而已,实际开发中会把WebAPi彻底抽离出来做为服务来进行数据传输,而这里可以正确访问到Index页面依然是以MVC为主导,WebAPi寄宿为WebHost,因此访问其目录下的内容毫无疑问会访问到,若是咱们将WebAPi彻底隔离出来也就是不依赖于IIS,利用Slef-Host来实现。(有关WebAPi中的WebHost以及Self-Host能够参考前面系列文章)。api
咱们来创建一个Windows应用程序起名为WebAPiReturnHtml。跨域
咱们新创建一个HttpServerHost类利用 HttpSelfHostServer 来监听Http请求,代码以下:服务器
public class HttpServerHost { /// <summary> /// HttpSelfHostServer实例 /// </summary> private HttpSelfHostServer _server; /// <summary> /// 启动HTTP服务器 /// </summary> public void Start() { var config = new HttpSelfHostConfiguration("http://localhost:8080"); config.MaxReceivedMessageSize = int.MaxValue; config.Routes.MapHttpRoute("Default", "api/{controller}/{action}"); //设置最大接收消息大小 config.MaxReceivedMessageSize = int.MaxValue; config.Formatters.Clear(); config.Formatters.Add(new JsonpFormatter()); _server = new HttpSelfHostServer(config); //容许跨域 _server.Configuration.MessageHandlers.Add(new CorsHandler()); _server.OpenAsync().Wait(); } }
咱们来演示下效果:函数
结果出错了,此时咱们应该注意应该以【管理员身份运行VS】才可。测试
咱们紧接着添加测试类以下:spa
public class HomeController : ApiController { [HttpGet] public string Test() { return "OK"; } }
咱们来看看演示结果:code
整个彻底抽离出WebAPi的过程就是这么简单,接着咱们回到开头的话题介绍,咱们在此项目下创建Index页面以下来访问试试:
结果以下:
此时则让咱们大失所望,彻底抽离出WebAPi此时则无妨访问到静态资源,此时咱们来利用读取文件字符串的形式来返回该静态资源,以下:
public HttpResponseMessage GetHtml() { var currentRunPath = AppDomain.CurrentDomain.BaseDirectory; var substringBin = currentRunPath.IndexOf("bin"); var path = currentRunPath.Substring(0, substringBin) + "Index.html"; var httpResponseMessage = new HttpResponseMessage(); httpResponseMessage.Content = new StringContent(File.ReadAllText(path), Encoding.UTF8); httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html"); return httpResponseMessage; }
咱们再来看看结果:
如上请求咱们能够设置路由特性,以下:
[HttpGet] [Route("Index")]
此时访问的路径则变为 localhost:8080/index 更加简洁。为了实现这样的需求只能无所不用其极,若是是加载图片呢,又该如何呢?固然也有解决办法,上述既然有读取字符串StringContent,那确定有读取图片的流,将上述
httpResponseMessage.Content = new StringContent(File.ReadAllText(path), Encoding.UTF8); httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
修改成以下便可:
httpResponseMessage.Content = new StreamContent(new FileStream(path, FileMode.Open)); httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("image/*");
那么如今问题来了,如何在上述Index.html页面中去请求JS呢?既然有了这个思路那就好办了,咱们继续往下看。
在控制器中返回JS定义以下:
[HttpGet] public HttpResponseMessage GetJS(string file) { var currentRunPath = AppDomain.CurrentDomain.BaseDirectory; var substringBin = currentRunPath.IndexOf("bin"); var path = currentRunPath.Substring(0, substringBin) + file; var httpResponseMessage = new HttpResponseMessage(); httpResponseMessage.Content = new StringContent(File.ReadAllText(path), Encoding.UTF8); httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("text/javascript"); return httpResponseMessage; }
在根目录下创建Index.js,去定义函数以下:
function btnClick() { alert("调用Index.js成功"); }
请求Index.js,以及结构以下:
接下来咱们再来进行演示:
到这里咱们达到咱们需求就已彻底结束。
这其中仍是有一点小小的疑惑,若是是在WebAPi2中须要启动 config.MapHttpAttributeRoutes(); 在上述请求Index方法时若是咱们添加 [Route(index)] ,此时请求index.js则需进行以下修改
<script type="text/javascript" src="GetJS?file=/index.js"></script>
修改成
<script type="text/javascript" src="api/home/GetJS?file=/index.js"></script>
可是在WebAPi2.2中应该没有了 config.MapHttpAttributeRoutes(); 想必是已经默认启动了该路由特性可是此时在上述请求Index方法时若定路由定性 [Route("index")] 此时根本请求不到该Index方法,不知是何缘故!
特殊需求有特殊的实现方法,若未有此需求的提出根本想不出这样去实现,同时很少加思考也会停滞不前感受这样作根本是不可能,可是并不是不可能,不是吗!可能说对于这样在WebAPi中存放页面不是太可取,若是能放在其余的UI,我又何须这样作呢,需求如此,只能这样作了,固然也能够直接将样式和脚本放在服务器上经过CDN来加载,实现的仅仅是显示一个列表从而进行其余几个操做而已,不须要进行这样的大动做。