详解ASP.NET MVC 解析模板生成静态页(RazorEngine)

简述

Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项。在早期的MVC版本中默认使用的是ASPX模板引擎,Razor在语法上的确不错,用起来非常方便,简洁的语法与.NET Framework 结合,广泛应用于ASP.NET MVC 项目。

我们在很多项目开发中会常常用到页面静态化,页面静态化有许多方式,最常见的就是类似很多PHP CMS种使用的 标签替换的方式(如:帝国CMS、EcShop等),还有很多都是伪静态,伪静态我们就不做过多解释,通过路由或Url重写来实现就可以了。Razor为我们提供了更加方便的模板解析方式,任何东西都是两方面的,技术也是如此,Razor解析模板虽然更加方便、简洁,但是对于模板制作人员来说也是有一定的技术要求,或者对于开发一套模板制作功能来说,考虑的要更多一些。我们不再去探究这些问题,我们更注重哪种技术更容易、更方便、更好的满足我们项目的需求。

如何使用RazorEngine

今天来简单介绍一下如何使用RazorEngine解析模板生成静态页面,RazorEngine它是基于微软的Razor之上,包装而成的一个可以独立使用的模板引擎。也就是说,保留了Razor的模板功能,但是使得Razor脱离于Asp.net MVC,能够在其它应用环境下使用,项目地址:RazorEngine_jb51.rar

首先我们去codeplex上下两个需要的dll http://razorengine.codeplex.com

看到网上很多介绍RazorEngine的基础用法的,讲解的都比较详细,对于RazorEngine运行原理很清晰,我们在这里就不重复介绍了。写这篇文章是对于很多新手同学来说比较喜欢“拿来主义”,基本的用法原理都能看懂,但是如何应用到项目中还是有些不是很清晰,我们只讲讲如何在项目中运用。

本文分为两部分:第一个部分,基本的单数据模型模板解析;第二部分,面向接口的多数据模型模板解析

第一个部分 基本的单数据模型模板解析

一、我们创建一个MVC项目,并且添加上面的两个DLL引用,然后我们新建一个简单的文章类

public class Articles
  {
    /// <summary>
    /// 文章ID
    /// </summary>
    public int Id { get; set; }
    /// <summary>
    /// 文章标题
    /// </summary>
    public string Title { get; set; }
    /// <summary>
    /// 文章内容
    /// </summary>
    public string Content { get; set; }
    /// <summary>
    /// 作者
    /// </summary>
    public string Author { get; set; }
    /// <summary>
    /// 发布时间
    /// </summary>
    public DateTime CreateDate { get; set; }
  }

二、我们新建一个Razor的Html模板

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title>@Model.Title</title>
</head>
<body>
  <h1>@Model.Title</h1>
  <p>作者:@Model.Author - 发布时间:@Model.CreateDate</p>
  <p>@Raw(Model.Content)</p>
</body>
</html>

说明:Model就是我们的文章实体类  在MVC的试图页cshtml中 我们一般都是在控制器里传递这个实体类 然后在视图页中 @model Models.Articles 来接收这个实体类 然后通过“@Model.”来输出内容,在Razor模板中是一样的,只是不用@model Models.Articles 来接收了,其它的语法跟在.cshtml试图页中是一样的,这么说多余了,因为写法不一样他就不是Razor了

三、我们写一个方法来获取模板页的Html代码

 /// <summary>
    /// 获取页面的Html代码
    /// </summary>
    /// <param name="url">模板页面路径</param>
    /// <param name="encoding">页面编码</param>
    /// <returns></returns>
    public string GetHtml(string url, System.Text.Encoding encoding)
    {
      byte[] buf = new WebClient().DownloadData(url);
      if (encoding != null) return encoding.GetString(buf);
      string html = System.Text.Encoding.UTF8.GetString(buf);
      encoding = GetEncoding(html);
      if (encoding == null || encoding == System.Text.Encoding.UTF8) return html;
      return encoding.GetString(buf);
    }

    /// <summary>
    /// 获取页面的编码
    /// </summary>
    /// <param name="html">Html源码</param>
    /// <returns></returns>
    public System.Text.Encoding GetEncoding(string html)
    {
      string pattern = @"(?i)\bcharset=(?<charset>[-a-zA-Z_0-9]+)";
      string charset = Regex.Match(html, pattern).Groups["charset"].Value;
      try { return System.Text.Encoding.GetEncoding(charset); }
      catch (ArgumentException) { return null; }
    }

四、我们写一个方法 用于生成Html静态页

 /// <summary>
    /// 创建静态文件
    /// </summary>
    /// <param name="result">Html代码</param>
    /// <param name="createpath">生成路径</param>
    /// <returns></returns>
    public bool CreateFileHtmlByTemp(string result, string createpath)
    {
      if (!string.IsNullOrEmpty(result))
      {
        if (string.IsNullOrEmpty(createpath))
        {
          createpath = "/default.html";
        }
        string filepath = createpath.Substring(createpath.LastIndexOf(@"\"));
        createpath = createpath.Substring(0, createpath.LastIndexOf(@"\"));
        if (!Directory.Exists(createpath))
        {
          Directory.CreateDirectory(createpath);
        }
        createpath = createpath + filepath;
        try
        {
          FileStream fs2 = new FileStream(createpath, FileMode.Create);
          StreamWriter sw = new StreamWriter(fs2, new System.Text.UTF8Encoding(false));//去除UTF-8 BOM
          sw.Write(result);
          sw.Close();
          fs2.Close();
          fs2.Dispose();
          return true;
        }
        catch { return false; }
      }
      return false;
    }

五、我们来写个方法调用静态模板,并且传递数据模型实体类 创建Html静态页

/// <summary>
    /// 解析模板生成静态页
    /// </summary>
    /// <param name="temppath">模板地址</param>
    /// <param name="path">静态页地址</param>
    /// <param name="t">数据模型</param>
    /// <returns></returns>
    public bool CreateStaticPage(string temppath, string path, RazorEngineTemplates.Models.Articles t)
    {
      try
      {
        //获取模板Html
        string TemplateContent = GetHtml(temppath, System.Text.Encoding.UTF8);

        //初始化结果
        string result = string.Empty;

        //解析模板生成静态页Html代码
        result = Razor.Parse(TemplateContent, t);

        //创建静态文件
        return CreateFileHtmlByTemp(result, path);
      }
      catch (Exception e)
      {
        throw e;
      }
    }

好了,大功告成,是不是很简单。

这里只是一个很简单的应用,没有读取数据,也没有列表,只有一个文章数据模型,下一部分我们将介绍 多模型模板解析,因为是多模型 所以 生成静态页面的时候 就不是传递一个具体模型实体类 我们会用到 反射,通过反射模型属性 获取数据,有不熟悉反射的可以提前研究一下,也可以直接看下一部分的反射代码也很简单的。

第二部分 面向接口的多数据模型模板解析

这一部分,我们介绍使用接口来解析模板,包括列表等多种模型解析,用到了Spring注入和反射还有接口等,有不熟悉的可以百度搜一下或者评论留言。

我们接着上面的示例,我们新建两个类库 一个是存放数据模型的 我们叫Domain;另外一个是接口和实现类的 我们叫Service,然后我们添加他们之间的引用

一、我们在Domain下创建几个测试类

Articles - 文章测试类

Company - 公司测试类

Column - 栏目测试类

TemplateView - 模型解析类(这个是不是比较弱智?我也没深入研究多个模型怎么反射出来 所以 我加了这么个算是公用的类 没有对应的数据表 只是解析模板的时候 作为中间件用用)

   public class Articles
  {
    /// <summary>
    /// 文章ID
    /// </summary>
    public int Id { get; set; }
    /// <summary>
    /// 文章标题
    /// </summary>
    public string Title { get; set; }
    /// <summary>
    /// 文章内容
    /// </summary>
    public string Content { get; set; }
    /// <summary>
    /// 作者
    /// </summary>
    public string Author { get; set; }
    /// <summary>
    /// 发布时间
    /// </summary>
    public DateTime CreateDate { get; set; }
  }
  public class Company
  {
    /// <summary>
    /// 公司Id
    /// </summary>
    public int Id { get; set; }
    /// <summary>
    /// 公司名称
    /// </summary>
    public string CompanyName { get; set; }
    /// <summary>
    /// 公司电话
    /// </summary>
    public string CompanyTel { get; set; }
    /// <summary>
    /// 联系人
    /// </summary>
    public string ContectUser { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime CreateDate { get; set; }
  }
   public class Column
  {
    /// <summary>
    /// 栏目ID
    /// </summary>
    public int Id { get; set; }
    /// <summary>
    /// 栏目名称
    /// </summary>
    public string Title { get; set; }
    /// <summary>
    /// 文章列表
    /// </summary>

    public virtual ICollection<Articles> Articles { get; set; }
  }
   public class TemplateView
  {
    /// <summary>
    /// ID
    /// </summary>
    public int Id { get; set; }
    /// <summary>
    /// 标题
    /// </summary>
    public string Title { get; set; }
    /// <summary>
    /// 内容
    /// </summary>
    public string Content { get; set; }
    /// <summary>
    /// 作者
    /// </summary>
    public string Author { get; set; }
    /// <summary>
    /// 时间
    /// </summary>
    public DateTime CreateDate { get; set; }
    /// <summary>
    /// 公司名称
    /// </summary>
    public string CompanyName { get; set; }
    /// <summary>
    /// 公司电话
    /// </summary>
    public string CompanyTel { get; set; }
    /// <summary>
    /// 联系人
    /// </summary>
    public string ContectUser { get; set; }
    /// <summary>
    /// 文章列表
    /// </summary>
    public virtual ICollection<Articles> Articles { get; set; }
  }

二、我们在Service下创建一个基础操作接口以及其实现类(里面的很多方法 比如:获取页面的Html代码、获取页面的编码以及创建静态文件等 是没有必要写在接口的 这个可以写到公用的类库里,因为这里就用到这么几个方法 所以我没有加公用类库 就直接写在这里面了)

/// <summary>
  /// 基础操作接口
  /// </summary>
  /// <typeparam name="T"></typeparam>
  public interface IRepository<T> where T : class
  {
    /// <summary>
    /// 解析模板生成静态页
    /// </summary>
    /// <param name="temppath">模板地址</param>
    /// <param name="path">静态页地址</param>
    /// <param name="t">数据模型</param>
    /// <returns></returns>
    bool CreateStaticPage(string temppath, string path, T t);    

    /// <summary>
    /// 获取页面的Html代码
    /// </summary>
    /// <param name="url">模板页面路径</param>
    /// <param name="encoding">页面编码</param>
    /// <returns></returns>
    string GetHtml(string url, System.Text.Encoding encoding);

    /// <summary>
    /// 获取页面的编码
    /// </summary>
    /// <param name="html">Html源码</param>
    /// <returns></returns>
    System.Text.Encoding GetEncoding(string html);

    /// <summary>
    /// 创建静态文件
    /// </summary>
    /// <param name="result">Html代码</param>
    /// <param name="createpath">生成路径</param>
    /// <returns></returns>
    bool CreateFileHtmlByTemp(string result, string createpath);
  }
/// <summary>
  /// 基础接口实现类
  /// </summary>
  /// <typeparam name="T"></typeparam>
  public abstract class RepositoryBase<T> : IRepository<T> where T : class
  {
    /// <summary>
    /// 解析模板生成静态页
    /// </summary>
    /// <param name="temppath">模板地址</param>
    /// <param name="path">静态页地址</param>
    /// <param name="t">数据模型</param>
    /// <returns></returns>
    public bool CreateStaticPage(string temppath, string path, T t)
    {
      try
      {
        //实例化模型
        var Entity = new Domain.TemplateView();

        //获取模板Html
        string TemplateContent = GetHtml(temppath, System.Text.Encoding.UTF8);
        //初始化结果
        string result = "";

        //反射赋值
        Type typeT = t.GetType();
        Type typeEn = Entity.GetType();

        System.Reflection.PropertyInfo[] propertyinfosT = typeT.GetProperties();

        foreach (System.Reflection.PropertyInfo propertyinfoT in propertyinfosT)
        {
          System.Reflection.PropertyInfo propertyinfoEn = typeEn.GetProperty(propertyinfoT.Name);
          if (propertyinfoEn != null && propertyinfoT.GetValue(t, null) != null)
          {
            propertyinfoEn.SetValue(Entity, propertyinfoT.GetValue(t, null), null);
          }
        }

        //很多时候 我们并没有创建复杂的主外键关系 例如栏目下的文章 我们仅仅是在文章表中添加了一个所属栏目ID的字段
        //并没有创建关联 这种情况下 我们直接获取栏目的时候 是获取不到文章列表的
        //包括很多自定义的模型和字段 比如 文章的内容 可能不跟文章一个表 而是一个单独的大数据字段表 这种情况下 我们的
        //TemplateView.Content就需要单独获取一下另一个数据模型里的 这个文章的内容 这种时候 我们可以在这里重新给他赋值

        //如 传入的模型是 文章
        //if(t is Domain.Articles)
        //{
        //  Entity.Content= 查询大数据字段表中这篇文章的内容;

        //}

        result = Razor.Parse(TemplateContent, Entity);

        return CreateFileHtmlByTemp(result, path);
      }
      catch (Exception e)
      {
        throw e;
      }
    }

    /// <summary>
    /// 获取页面的Html代码
    /// </summary>
    /// <param name="url">模板页面路径</param>
    /// <param name="encoding">页面编码</param>
    /// <returns></returns>
    public string GetHtml(string url, System.Text.Encoding encoding)
    {
      byte[] buf = new WebClient().DownloadData(url);
      if (encoding != null) return encoding.GetString(buf);
      string html = System.Text.Encoding.UTF8.GetString(buf);
      encoding = GetEncoding(html);
      if (encoding == null || encoding == System.Text.Encoding.UTF8) return html;
      return encoding.GetString(buf);
    }

    /// <summary>
    /// 获取页面的编码
    /// </summary>
    /// <param name="html">Html源码</param>
    /// <returns></returns>
    public System.Text.Encoding GetEncoding(string html)
    {
      string pattern = @"(?i)\bcharset=(?<charset>[-a-zA-Z_0-9]+)";
      string charset = Regex.Match(html, pattern).Groups["charset"].Value;
      try { return System.Text.Encoding.GetEncoding(charset); }
      catch (ArgumentException) { return null; }
    }

    /// <summary>
    /// 创建静态文件
    /// </summary>
    /// <param name="result">Html代码</param>
    /// <param name="createpath">生成路径</param>
    /// <returns></returns>
    public bool CreateFileHtmlByTemp(string result, string createpath)
    {
      if (!string.IsNullOrEmpty(result))
      {
        if (string.IsNullOrEmpty(createpath))
        {
          createpath = "/default.html";
        }
        string filepath = createpath.Substring(createpath.LastIndexOf(@"\"));
        createpath = createpath.Substring(0, createpath.LastIndexOf(@"\"));
        if (!Directory.Exists(createpath))
        {
          Directory.CreateDirectory(createpath);
        }
        createpath = createpath + filepath;
        try
        {
          FileStream fs2 = new FileStream(createpath, FileMode.Create);
          StreamWriter sw = new StreamWriter(fs2, new System.Text.UTF8Encoding(false));//去除UTF-8 BOM
          sw.Write(result);
          sw.Close();
          fs2.Close();
          fs2.Dispose();
          return true;
        }
        catch { return false; }
      }
      return false;
    }
  }

三、我们分别创建 文章管理、公司管理、栏目管理的接口和实现类 并且他们都集成基础操作

   /// <summary>
  /// 文章管理
  /// </summary>
   public interface IArticleManage:IRepository<Domain.Articles>
  {
  }
  public class ArticleManage:RepositoryBase<Domain.Articles>,IArticleManage
  {
  }

  /// <summary>
  /// 公司管理
  /// </summary>
  public interface ICompanyManage:IRepository<Domain.Company>
  {
  }
  public class CompanyManage:RepositoryBase<Domain.Company>,ICompanyManage
  {
  }

  //栏目管理
  public interface IColumnManage:IRepository<Domain.Column>
  {
  }
  public class ColumnManage:RepositoryBase<Domain.Column>,IColumnManage
  {
  }

四、注入Xml

<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
 <description>Spring注入Service,容器指向本层层封装的接口</description>
 <object id="Service.ArticleManage" type="Service.ArticleManage,Service" singleton="false">
 </object>
 <object id="Service.ColumnManage" type="Service.ColumnManage,Service" singleton="false">
 </object>
 <object id="Service.CompanyManage" type="Service.CompanyManage,Service" singleton="false">
 </object>
</objects>

五、我们分别初始化一个文章类、一个公司类(没有管理数据表,它下面没有文章列表 栏目模型我就不初始化了,怎么输出列表 大家可以参考下 栏目模板)

  public class HomeController : Controller
  {
    /// <summary>
    /// 声明一下注入接口
    /// </summary>
    public IArticleManage ArticleManage = Spring.Context.Support.ContextRegistry.GetContext().GetObject("Service.ArticleManage") as IArticleManage;
    public ICompanyManage CompanyManage = Spring.Context.Support.ContextRegistry.GetContext().GetObject("Service.CompanyManage") as ICompanyManage;
    public IColumnManage ColumnManage = Spring.Context.Support.ContextRegistry.GetContext().GetObject("Service.ColumnManage") as IColumnManage;

    public ActionResult Index()
    {
      //初始化一个文章数据模型
      var entityArticle = new Domain.Articles() { Id = 1, Title = "这里是文章标题", Content = "<span style=\"color:red;\">这里是文章内容</span>", Author = "张三", CreateDate = DateTime.Now };

      //初始化一个公司数据模型
      var entityCompany = new Domain.Company() { Id = 1, CompanyName = "这里是公司名称", CompanyTel = "公司电话", ContectUser = "张三", CreateDate = DateTime.Now };

      //调用方法生成静态页面
      ArticleManage.CreateStaticPage(Server.MapPath("/Templates/Temp_article.html"), Server.MapPath("/Pages/news/" + DateTime.Now.ToString("yyyyMMddHHmmss") + "1.html"), entityArticle);
      CompanyManage.CreateStaticPage(Server.MapPath("/Templates/Temp_company.html"), Server.MapPath("/Pages/news/" + DateTime.Now.ToString("yyyyMMddHHmmss") + "2.html"), entityCompany);

      return View();
    }

    public ActionResult About()
    {
      ViewBag.Message = "Your application description page.";

      return View();
    }

    public ActionResult Contact()
    {
      ViewBag.Message = "Your contact page.";

      return View();
    }

  }

六、这是测试的简单的文章模板、公司模板和栏目模板

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>@Model.Title</title>
</head>
<body>
  <h1>@Model.Title</h1>
  <p>作者:@Model.Author - 发布时间:@Model.CreateDate</p>
  <p>@Raw(Model.Content)</p>
</body>
</html>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title></title>
</head>
<body>
  <p>公司名称:@Model.CompanyName</p>
  <p>公司电话:@Model.CompanyTel</p>
  <p>联系人:@Model.ContectUser</p>
  <p>创建时间:@Model.CreateDate</p>
</body>
</html>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title></title>
</head>
<body>
  <p>栏目标题: @Model.Title</p>
  <p>
    文章列表
    <ul>
      @foreach(var item in @Model.Articles)
      {
      <li>
        <a href="">
          <span>@item.Title</span>
          <span>@item.Author</span>
          <span>@item.CreateDate</span>
        </a>
      </li>
      }
    </ul>
  </p>
</body>
</html>

我们运行一下,大功告成~~~

怎么排序?怎么获取前几条?怎么格式化日期时间?怎么分页?

这可是Razor啊,这都不需要再多讲了吧,简单一说,如果你传入数据前没有事先排序或者获取前几条,这些操作要做模板里操作 那跟在.cshtml里基本是一样的

@foreach(var item in @Model.ListColumn)
{

 <div >
@if (@item.LinkUrl==null)
  {
    <ul>
@foreach(var article in @item.COM_ARTICLE.Take(15).OrderByDescending(p=>p.UpDateDate))
{

<li>
      <a href="@article.LinkUrl" rel="external nofollow" class="gd-a">
        <div>@article.Title</div></a>
      </li>
}
 </ul>
   }
  else
   {

  }
</div>
}

应用还是很广泛的,而且解析代码相对于标签替换来说十分简洁、高效。有时间可以多研究研究,改天有空写一个模板替换标签的供大家参考一下。有人会说那我还得教前台制作Razor语法,这种说法我们没法去置评,标签替换你仍然要教他如何使用标签啊,所以是不是复杂并不是探究的主题,想要前台制作人员更方便的制作一套模板语法并不是主要因素,比如我们可以做一套方便的模板制作,用户点击一下就生成代码,或者直接做成可视化的,这可能让我们的程序员要耗费更多的精力,但是一劳永逸,标签替换方式你仍然要给前台制作人员一套标签规范和语法,况且后台解析异常的庞大和复杂。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 使用Asp.net Mvc3 Razor视图方式扩展JQuery UI Widgets方法介绍

    JQuery UI Widgets是本人非常喜欢的一套前端JS组件,日常开发中基于原有的jquery ui widget js代码进行开发,需要写非常多的重复代码,同时一些现有组件无法满足需求的情况下,需要对现有组件进行扩展,本文使用一套基于jquery ui 的扩展js组件---jtable (http://www.jtable.org),包含了基本的列表和编辑窗口,比起jqGrid,jquery easyui grid或者extjs grid,jtable的代码非常简洁.对于grid功能要求

  • 详解ASP.NET MVC 利用Razor引擎生成静态页

    最近在研究ASP.NET MVC生成静态页,那么今天也算个学习笔记吧! 实现原理及步骤: 1.通过ViewEngines.Engines.FindView查找到对应的视图,如果是部分视图,则用:ViewEngines.Engines.FindPartialView: 2.设置上下文对象里的Model: 3.调用视图的Render()方法,将渲染结果保存到物理静态文件: using System; using System.IO; using System.Text; using System.W

  • ASP.NET MVC使用RazorEngine解析模板生成静态页

    简述 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项.在早期的MVC版本中默认使用的是ASPX模板引擎,Razor在语法上的确不错,用起来非常方便,简洁的语法与.NET Framework 结合,广泛应用于ASP.NET MVC 项目. 我们在很多项目开发中会常常用到页面静态化,页面静态化有许多方式,最常见的就是类似很多PHP CMS种使用的 标签替换的方式(如:帝国CMS.EcShop等),还有很多都是伪静态,伪静态我们就不做过多解释,通过路由或Url

  • asp.net实现在非MVC中使用Razor模板引擎的方法

    本文实例讲述了asp.net实现在非MVC中使用Razor模板引擎的方法.分享给大家供大家参考.具体分析如下: 模板引擎介绍 Razor.Nvelocity.Vtemplate,Razor一般在MVC项目中使用,这里介绍在非MVC项目中的用法. 如何在非MVC中使用Razor模板引擎 借助于开源的RazorEngine,我们可以在非asp.net mvc项目中使用Razor引擎,甚至在控制台.WinForm项目中都可以使用Razor(自己开发代码生成器) 如何使用Razor 环境搭建: ① 添加

  • ASP.NET MVC4 Razor模板简易分页效果

    一.无数据提交 第一步,建立一个 Controller命名为PageIndex的空控制器,自定义一个方法如下: public ActionResult PageIndex(string action, string controller, int currentPage, int pageCount) { //int count = db.Product.Count(); ViewBag.PageCount = pageCount;//从操作中获取总数据页数将传入分页视图页面 ViewBag.C

  • 教你如何在 Javascript 文件里使用 .Net MVC Razor 语法

    相信大家都试过在一个 View 里嵌套使用 javascript,这时就可以直接使用 Razor 语法以调用 .NET 的一些方法.如以下代码嵌套在一个 Razor 的 View 里: <script> var currDate = '@DateTime.Now'; //直接调用.NET的方法 console.log(currDate) </script> 但另一种情况是,如果我想在一个独立的 JS 文件里使用 Razor,那以上的方法可行不通,因为MVC不会直接解释JS文件,只有

  • 详解ASP.NET MVC 解析模板生成静态页(RazorEngine)

    简述 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项.在早期的MVC版本中默认使用的是ASPX模板引擎,Razor在语法上的确不错,用起来非常方便,简洁的语法与.NET Framework 结合,广泛应用于ASP.NET MVC 项目. 我们在很多项目开发中会常常用到页面静态化,页面静态化有许多方式,最常见的就是类似很多PHP CMS种使用的 标签替换的方式(如:帝国CMS.EcShop等),还有很多都是伪静态,伪静态我们就不做过多解释,通过路由或Url

  • 详解ASP.NET MVC的整个生命周期

    目录 一.介绍 二.MVC生命周期详述 View的初始化和渲染呈现 三.结束 一.介绍 我们做开发的,尤其是做微软技术栈的,有一个方向是跳不过去的,那就是MVC开发.我相信大家,做ASP.NET MVC 开发有的有很长时间,当然,也有刚进入这个行业的.无论如何,如果有人问你,你知道ASP.NET MVC的生命周期吗?你知道它的来世今生吗?你知道它和 ASP.NET WEBFORM 有什么区别吗?估计,这些问题,有很多人会答不上来,或者说不清楚.今天,我就把我的理解写出来,也是对我自己学习的一次回

  • 详解ASP.NET MVC的筛选器

    在ActionInvoker对Action的执行过程中,除了通过利用ActionDescriptor对Action方法的执行,以及之前进行的Model绑定与验证之外,还具有一个重要的工作,那就是对相关筛选器(Filter)的执行.ASP.NET MVC的筛选器是一种基于AOP(面向方面编程)的设计,我们将一些非业务的逻辑实现在相应的筛选器中,然后以一种横切(Crosscutting)的方式应用到对应的Action方法.当Action方法执行前后,这些筛选器会自动执行.ASP.NET MVC提供了

  • 详解ASP.NET MVC 常用扩展点:过滤器、模型绑定

    一.过滤器(Filter) ASP.NET MVC中的每一个请求,都会分配给对应Controller(以下简称"控制器")下的特定Action(以下简称"方法")处理,正常情况下直接在方法里写代码就可以了,但是如果想在方法执行之前或者之后处理一些逻辑,这里就需要用到过滤器. 常用的过滤器有三个:Authorize(授权过滤器),HandleError(异常过滤器),ActionFilter(自定义过滤器),对应的类分别是:AuthorizeAttribute.Han

  • 详解ASP.NET MVC下的异步Action的定义和执行原理

    Visual Studio提供的Controller创建向导默认为我们创建一个继承自抽象类Controller的Controller类型,这样的Controller只能定义同步Action方法.如果我们需要定义异步Action方法,必须继承抽象类AsyncController.这篇问你讲述两种不同的异步Action的定义方法和底层执行原理. 一.基于线程池的请求处理 ASP.NET通过线程池的机制处理并发的HTTP请求.一个Web应用内部维护着一个线程池,当探测到抵达的针对本应用的请求时,会从池

  • 详解Asp.Net MVC——控制器与动作(Controller And Action)

    一.理解控制器 1.1.什么是控制器 控制器是包含必要的处理请求的.NET类,控制器的角色封装了应用程序逻辑,控制器主要是负责处理请求,实行对模型的操作,选择视图呈现给用户. 简单理解:实现了IController接口,修饰符必须是public,不能是抽象的,不能是泛型的,类名必须以Controller结尾. 在MVC框架中,控制器类必须实现System.Web.Mvc命名空间下的IController接口,如上图所示,这是一个非常简单的接口,该接口仅有一个Execute方法,当请求该控制器时E

  • 详解Asp.Net MVC的Bundle捆绑

    大多数浏览器会对同一域名的请求限制请求数量,一般是在8个以内.每次最多可以同时请求8个,要是资源多于8个,那么剩下的就要排队等待请求了.所以为了提高首次加载页面的速度.提高请求并发请求数量,降低请求次数就是一个很重要的点. Bundle Asp.Net MVC4和.NET Framework4.5提供了支持捆绑和压缩的新类库System.Web.Optimization. 该类库提供了如下特性: 捆绑-将多个资源文件(javascript,css)合并成一个单独的文件,但是合并成的单独文件必须是

  • 详解ASP.NET MVC之下拉框绑定四种方式

    前言 上两节我们讲了文件上传的问题,关于这个上传的问题还未结束,我也在花时间做做分割大文件处理以及显示进度的问题,到时完成的话再发表,为了不耽误学习MVC其他内容的计划,我们今天开始好好讲讲关于MVC中下拉框中绑定枚举的几种方式. 话题引入 一般在下拉框中绑定数据的话,分为几种情况. (1)下拉框中的数据是写死的,我们直接给出死代码即可. (2)下拉框中的数据从数据库中读取出来,从而进行显示. (3)下拉框中直接用枚举显示. (4)下拉框中一个选择的值改变另外一个下拉框中的值. 关于下拉框中绑定

随机推荐