ASP.NET MVC 在控制器中获取某个视图动态的HTML代码

 

如果我们需要动态的用AJAX从服务器端获取HTML代码,拼接字符串是一种不好的方式,所以我们将HTML代码写在cshtml文件中,然后通过代码传入model,动态获取cshtml中的HTML代码

当然,我们想要使用通用的方法去获取cshtml,就必须重写RazorViewEngine视图引擎,配置视图搜索位置

在查找一个视图时,Razor视图引擎遵循了MVC框架早期版本建立起来的约定。例如,如果你请求与Home控制器相关的Index视图,Razor会审查这样的视图列表:

~/Views/Home/Index.cshtml
● ~/Views/Home/Index.vbhtml
● ~/Views/Shared/Index.cshtml
● ~/Views/Shared/Index.vbhtml

正如你现在知道的,Razor实际上不会在磁盘上查找这些视图文件,因为它们还没有被编译成C#类。Razor查找的是表示这些视图的编译类。.cshtml文件是含有C#语句的模板(我们正在使用的这种),而.vbhtml文件含有Visual Basic语句。

你可以通过生成一个RazorViewEngine子类,来改变Razor搜索的这种视图文件。这个类是Razor的IViewEngine实现。它建立于一组基类之上,这些类定义一组用来确定搜索哪种视图文件的属性。这些属性如表所描述。

Property
属性
Description
描述
Default Value
默认值
ViewLocationFormats
MasterLocationFormats
PartialViewLocationFormats
The locations to look for views, partial views, and layouts
查找视图、分部视图、以及布局的位置
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
AreaViewLocationFormats
AreaMasterLocationFormats
AreaPartialViewLocationFormats
The locations to look for views, partial views, and layouts for an area
查找一个区域的视图、分部视图、及布局的位置
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/{1}/{0}.vbhtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.vbhtml"

这些属性先于Razor的引入,这是每组三个属性具有相同值的原因。每个属性是一个字符串数组,它们是用复合字符串格式化符号来表示的。以下是与占位符对应的参数值:
● {0} represents the name of the view.
{0} 表示视图名
● {1} represents the name of the controller.
{1} 表示控制器名
● {2} represents the name of the area.
{2} 表示区域名
为了修改搜索位置,你要生成一个派生于RazorViewEngine的新类,并修改表所描述的一个或多个属性值。

在Infrastructure文件夹中新建一个CustomRazorViewEngine类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace MvcApplication1.Infrastructure
{
public class CustomRazorViewEngine : RazorViewEngine
{
public CustomRazorViewEngine()
{ ViewLocationFormats = new string[] { "~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared_PartialView/{0}.cshtml"//指定查找某个文件的路径
}; PartialViewLocationFormats = new string[] { "~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared_PartialView/{0}.cshtml"////指定查找某个文件的路径
};
} }
}

我们在Global.asax的Application_Start方法中,用ViewEngines.Engines集合来注册我们的这个派生视图引擎,像这样:

 protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new CustomRazorViewEngine()); WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}

获取html字符串的方法以及如何调用

public class HomeController : Controller
{
//
// GET: /Home/ public ActionResult Index()
{
string html = this.ControllerContext.RenderViewToString("_CommonPartial", new UserViewModel() { UserName="haha"});
return View(new UserViewModel() { IsEnable = false, UserCode = "aa" });
} } public static class HelperExtensions
{
public static string RenderViewToString(this ControllerContext context, string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = context.RouteData.GetRequiredString("action"); context.Controller.ViewData.Model = model; using (var sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(context, viewName);
var viewContext = new ViewContext(context,
viewResult.View,
context.Controller.ViewData,
context.Controller.TempData,
sw);
try
{
viewResult.View.Render(viewContext, sw);
}
catch (Exception ex)
{
throw;
} return sw.GetStringBuilder().ToString();
}
}
}

ASP.NET MVC学习之路由篇(2)

 

ASP.NET MVC学习之路由篇(1)后继续学习。

7.解决与物理路径的冲突

当发送一个请求至ASP.NET MVC时,其实会检查网站中存不存在这个请求的物理路径文件,如果存在的话,就会直接将这个物理文件返回。但是有时候我们需要它执行控制器的某个方法,而不是直接将这个物理文件返回。那么我们就需要这节知识。下面我们先在网站根目录中新建一个 Test.html ,在其中随便写上一些内容,然后访问。再在RouteConfig.cs中写入如下代码:

 1     public class RouteConfig
2 {
3 public static void RegisterRoutes(RouteCollection routes)
4 {
5 routes.RouteExistingFiles = true;
6
7 routes.MapRoute(
8 name: "Default2",
9 url: "Test.html",
10 defaults: new { controller = "Home", action = "List" }
11 );
12 }
13 }

这个时候我们再重新刷新浏览器,那么我们就可以看到控制器返回的结果了,这样我们就解决了物理路径和路由之间的冲突问题了。

8.绕过路由系统

如果我们有一些URL路径不希望通过路由系统,那么我们就可以利用这节知识。

下面是RouteConfig.cs的内容:

 1     public class RouteConfig
2 {
3 public static void RegisterRoutes(RouteCollection routes)
4 {
5 routes.IgnoreRoute("webResources.axd{*pathinfo}");
6
7 routes.MapRoute(
8 name: "Default2",
9 url: "Test.html",
10 defaults: new { controller = "Home", action = "List" }
11 );
12 }
13 }

9.自定义路由系统

如果上面的技术还无法解决你的问题,那么我们下面将会介绍如何自定义路由系统。自定义路由系统只需要继承RouteBase并实现两个方法,如下:

(1):GetRouteData

(2):GetVirtualPath

下面是我写的一个简单示例,用来判断访问者是否是移动设备,如果是移动设备则路由到前缀为M的控制器处理请求,否则返回NULL交由默认的路由

处理,下面为我的源码:

 1 public class CustomRouteBase : RouteBase
2 {
3 private List<String> userAgent;
4
5 public CustomRouteBase(params String[] userAgents)
6 {
7 userAgent = userAgents.ToList();
8 }
9
10 public override RouteData GetRouteData(HttpContextBase httpContext)
11 {
12 RouteData rd = new RouteData(this, new MvcRouteHandler());
13 Regex r = new Regex(@"/(\w+)", RegexOptions.IgnoreCase);
14 MatchCollection mc = r.Matches(httpContext.Request.Path);
15 String agent = httpContext.Request.UserAgent.ToLower();
16 foreach (String item in userAgent)
17 {
18 if (agent.Contains(item))
19 {
20 if (mc.Count >= 2)
21 {
22 rd.Values.Add("controller", "M" + mc[0].Groups[1].Value.ToString());
23 rd.Values.Add("action", mc[1].Groups[1].Value.ToString());
24 }
25 else
26 {
27 rd.Values.Add("controller", "MHome");
28 rd.Values.Add("action", "Index");
29 }
30 return rd;
31 }
32 }
33 return null;
34 }
35
36 public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
37 {
38 return null;
39 }
40 }

最后我们将该自定义路由添加进来(RouteConfig.cs):

 1     public class RouteConfig
2 {
3 public static void RegisterRoutes(RouteCollection routes)
4 {
5 routes.Add(new CustomRouteBase("iphone", "ipad", "android"));
6
7 routes.MapRoute(
8 name: "Default2",
9 url: "Test.html",
10 defaults: new { controller = "Home", action = "List" }
11 );
12 }
13 }

现在你新建一个MHome的控制器,然后访问看看(建议使用Google浏览器,并通过开发者工具改变UserAgent即可快速看到效果)。

10.自定义路由处理程序

或许你会觉得ASP.NET MVC的控制器太麻烦,相比而言有些功能你更希望使用一般处理程序。但是访问的时候必须使用物理路径又发觉麻烦,那么通过学习这节,你将可以将一般处理程序也加入到路由中,并且可控性很强。

首先我们必须新建一个实现IRouteHandler接口的类:

 1     public class DonwloadHandler : IRouteHandler
2 {
3
4 public IHttpHandler GetHttpHandler(RequestContext requestContext)
5 {
6 return new CustomHandler();
7 }
8 }
9
10 public class CustomHandler : IHttpHandler
11 {
12
13 public bool IsReusable
14 {
15 get { return false; }
16 }
17
18 public void ProcessRequest(HttpContext context)
19 {
20 context.Response.Write("download model");
21 }
22 }

你们可以看到上面的源码,我是直接在下面新建了一个实现IHttpHandler的类,并且在GetHttpHandler中将该类的实例返回,当然你还可以在这个方法中进行判断以便根据实际情况交由不同的一般处理程序去处理请求。

下面就是将这个路由处理程序添加到路由中,这里我们映射到MyTest这个路径:

 1     public class RouteConfig
2 {
3 public static void RegisterRoutes(RouteCollection routes)
4 {
5 routes.Add(new Route("MyTest",new DonwloadHandler()));
6
7 routes.MapRoute(
8 name: "Default2",
9 url: "Test.html",
10 defaults: new { controller = "Home", action = "List" }
11 );
12 }
13 }

接着我们访问http://localhost:2392/MyTest就可以看到结果了。

在满足必要的经济的条件下,研究更佳高深的技术.满足自己的野心
 
分类: ASP.NET MVC
分类: ASP.NET MVC
 

MVC 在控制器中获取某个视图动态的HTML代码的更多相关文章

  1. ASP.NET MVC 在控制器中获取某个视图动态的HTML代码

    如果我们需要动态的用AJAX从服务器端获取HTML代码,拼接字符串是一种不好的方式,所以我们将HTML代码写在cshtml文件中,然后通过代码传入model,动态获取cshtml中的HTML代码 当然 ...

  2. ASP.Net MVC 在控制器中获取View中的form表单值的方法

    在网站开发中,我们常常需要用到表单提交的方式,那么在MVC中是如何获取到表单中的数据呢?下面我们来介绍以下几种方式 首先我们先看看View前台页面 添加一个控制器 我们再看看前台页面的代码 @{ La ...

  3. MVC教程二:从控制器中获取URL的值

    一.从控制器中获取URL的值有三种方式: 1.使用Request.QueryString[] 例如: string value = Request.QueryString["BookId&q ...

  4. spring mvc在Controller中获取ApplicationContext

    spring mvc在Controller中获取ApplicationContext web.xml中进行正常的beans.xml和spring-mvc.xml的配置: 需要在beans.xml中进行 ...

  5. ASP.NET在MVC控制器中获取Form表单值的方法

    在网站开发中我们经常需要用到表单,那么,在前台页面的表单中提交到后台控制器后,后台控制器如何接收表单提交过来的数据呢?下面我们介绍几种常用的方法. 我们先看看前台页面,这里我们用一个用户名和密码的表单 ...

  6. 在ASP.NET MVC控制器中获取链接中的路由数据

    在ASP.NET MVC中,在链接中附加路由数据有2种方式.一种是把路由数据放在匿名对象中传递: <a href="@Url.Action("GetRouteData&quo ...

  7. ASP.NET MVC之控制器传递数据到视图的四种方式

    前奏 1. 在新建项目中的Models文件下,新建Products类: public class Products { public int Id { get; set; } public strin ...

  8. 控制器中获取Field值

    在ASP.NET MVC程序中,我们需要POST Data到制器中,是有很多方法.但是我们想在控制器中,获取Feild值呢?怎样获取?你可以留意到有一个类FormCollection.它能帮助到我们解 ...

  9. asp.net mvc 在View中获取Url参数的值

    如果url是 /home/index?id=3 直接Request就ok. 但是如果路由设定为:{controller}/{action}/{id} url是 /home/index/3   这时想在 ...

随机推荐

  1. android之Fragment(官网资料翻译)

    Fragment要点 Fragment作为Activity界面的一部分组成出现 能够在一个Activity中同一时候出现多个Fragment,而且,一个Fragment亦可在多个Activity中使用 ...

  2. 原因好消息: PSP游戏自己主动算法设计(两)

    这是我们讲的传说中的一项措施A×算法.事实上,类上传之前似小件,下面我们分析一下它去 毕竟,在游戏程序,我们从移动一个点到另一个点.和得到的轨迹的最短距离,类别似这样的算法以及几个.运营效率几乎是相同 ...

  3. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(14)-主框架搭建

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(14)-主框架搭建    ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2 ...

  4. 使用 Eclipse 的 SVN 主要插件创建项目/支/标签

    原文 阅读 Mark Phippard 该博客以及<Subversion 与版本号控制>之后,我了解到 分支/标签 是 SVN 非常棒的特性之中的一个.但我在使用推荐的 "tru ...

  5. shell变量赋值进阶

    首先,要理解shell中变量的3种赋值情况: unset 例子. unset a 空字符串, null 例子. a='' 非空,即不是unset,并且不是空字符串 例子: a=1 or a=b等 然后 ...

  6. Effective C++之‘宁以pass-by-reference-to-const替换pass-by-value’

    Effective C++之'宁以pass-by-reference-to-const替换pass-by-value' 缺省情况下C++以by value 方式(一个继承自C的方式)传递对象至函数.除 ...

  7. mysql中国的内容php网页乱码问题

    1.更改mysql编码在数据库 character_set_server=utf8 init_connect='SET NAMES utf8' 加入这两行 2.又第一次启动mysql数据库 版权声明: ...

  8. REUSEADDR 选项

    一般而言,对于处理2MSL状态的套接字(一般为服务端套接字)是不允许接受从同一客户端重新发起一个新的连接的,但是套接字编程系统接口允许应用程序通过设置一个REUSEADDR选项,使处于2MSL状态的套 ...

  9. Microsoft dotnetConf 2015

    Microsoft dotnetConf 2015 一些整理   dotnetConf 2015 直播计划: 第一天 (10 个主讲) - .NET Product Teams 主讲人为 .NET 产 ...

  10. 转载+自练(莫喷)怎样在cocos2d 2.1.4里面使用动画和Texture Packer

    本文实践自 Ray Wenderlich.Tony Dahbura 的文章<How to Use Animations and Sprite Sheets in Cocos2D 2.X>, ...