zoukankan      html  css  js  c++  java
  • (转)刚用MVC完成一个小项目,总结一些MVC技巧

    刚用MVC完成了一个小项目,MVC技术又有了一次提升,所以,再次写一点总结性的东西。

    开发环境:Visual Studio 2010 RC, MVC 2 RC, Entity Framework, SQL Server 2008

    1、不对IIS做任何修改,如何在IIS6下运行MVC?

    这个可以参考我前面一篇文章

    (原创,和微软官方做法不同,可以不修改IIS设置就达到目的)

    传送门:http://www.cnblogs.com/dozer/archive/2010/02/13/run-MVC-in-IIS6.html

    2、不同Areas的Controller重复导致的问题

    两个不同的Areas会有不同的命名空间,但是会有相同的 Controller

    而在网站MapRoute的时候却只能识别 Controller,因此会出现错误。

    假设,我在新建一个MVC项目后,直接新建一个Areas,并且命名为Admin,新建一个Home Controller

    运行,弹出以下错误:

    “/”应用程序中的服务器错误。

    The controller name 'Home' is ambiguous between the following types:
    MvcApplication1.Controllers.HomeController
    MvcApplication1.Areas.Admin.Controllers.HomeController

    遇到这种情况,只要这样就可以了

    context.MapRoute(
    "Web_default",
    "{controller}/{action}/{id}",
    new {controller="Home", action = "Index", id = "" },
    new string[] { "MvcApplication1.Areas.Web.Controllers" }
    );

    调用 MapRoute 的时候在后面多传入一个 String[] ,并且填入你需要 Route 的那个 Areas 的 Controller 所在的命名空间

    注意!2个地方都要改

    3、关于Filter

    MVC提供的4个Filter很方便,但是有一个问题,Filter中不能直接调用 ViewData,TempData等字段。

    虽然可以在传入的 filterContext 中调用到,但是很不方便。

    这时候,其实可以把4个Filter继承一下,自己写一个新的,并在内部放入ViewData等私有字段

    用 IAuthorizationFilter 来举个例子:

    public abstract class BaseFilterAttribute : FilterAttribute
    {
    //这里可以根据自己的喜好来设定
    protected HttpSessionStateBase Session;
    protected ModelStateDictionary State;
    protected ViewDataDictionary ViewData;
    protected TempDataDictionary TempData;
    protected HttpRequestBase Request;
    protected Dictionary<string, string> RouteValues;
    protected UrlHelper Url;

    protected void Initialize(ControllerContext filterContext)
    {
    //初始化
    Request
    = filterContext.RequestContext.HttpContext.Request;
    RouteValues
    = new Dictionary<string, string>();
    foreach (var v in filterContext.RequestContext.RouteData.Values)
    {
    RouteValues.Add(v.Key,v.Value.ToString());
    }
    ViewData
    = filterContext.Controller.ViewData;
    TempData
    = filterContext.Controller.TempData;
    State
    = ViewData.ModelState;
    Session
    = filterContext.RequestContext.HttpContext.Session;
    Url
    = new UrlHelper(filterContext.RequestContext);
    }
    }

    public abstract class AuthorizationFilter : BaseFilterAttribute, IAuthorizationFilter
    {
    public void OnAuthorization(AuthorizationContext filterContext)
    {
    //调用初始化函数
    Initialize(filterContext);
    onAuthorization(filterContext);
    }
    //这里把原来的 OnAuthorization 替换了一下
    public abstract void onAuthorization(AuthorizationContext filterContext);
    }

    然后需要使用 IAuthorizationFilter 的时候只要继承上面的 AuthorizationFilter 即可

    4、MVC中如何实现弹出一个Javascript对话框,并且跳转?

    大家觉得MVC的架构变了,但其实原理和Asp.net一样,还是用 Response来输出数据

    所以,只要在 Action 的 Return 函数前调用 Response.Write("text"); 即可实现。

    其实和以前一样,下面举个例子,在一个页面中弹出一个对话框后再跳转到别的页面

    public ActionResult Test()
    {
    //弹出对话框
    Response.Write(
    <script>alert('test');</script>));
    //跳转到index
    Response.Write(
    "<script>window.location.href='" + Url.Action("index") + "';</script>");
    return null;
    }

    5、Web.Debug.config 和 Web.Release.config 的用法

    利用 Web.config, Web.Debug.config, Web.Release.config

    可以在不同环境下生成3中不同的Web.config版本

    在VS中调试的时候,直接使用Web.config

    用Debug发布的时候,使用Web.Debug.config

    用Release发布的时候,使用Web.Release.config

    然后,这三个文件怎么用呢?

    你可以实现 Web.config 存在一个字段,然后当发布的时候用 Web.Debug.config 内的字段替换掉

    也可以本来不存在,发布的时候添加

    更可以本来存在,发布的时候删除

    这里就做简单的介绍,介绍一种替代的方法:

    代码
    //Web.config下,假设有这个字段
    <connectionStrings>
    <add name="ModelContainer"
    connectionString
    ="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=192.168.174.131,1433;Initial Catalog=Port80;User ID=port80;Password=port80;MultipleActiveResultSets=True&quot;"
    providerName
    ="System.Data.EntityClient"/>
    </connectionStrings>

    //在Web.Debug.config下

    <connectionStrings>
    <add name="ModelContainer"
    connectionString
    ="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.\sqlexpress;Initial Catalog=Port80;Integrated Security=True&quot;"
    providerName
    ="System.Data.EntityClient"
    xdt:Transform
    ="Replace"
    xdt:Locator
    ="Match(name)"/>
    </connectionStrings>

    这样,在用Debug发布的时候,那个字段就会被替换掉,具体用法在Web.Debug.config文件内写了一个网站,上面有全部的语法

    6、MVC中捕捉错误

    MVC中,有一个Filter可以捕捉错误,但是它的用法是利用Attribute来实现的,而且只能加在Controller和Action上,所以不能捕捉别出的错误

    其实理论上所有的错误肯定产生于Controller中,但有2种情况下,就不会被捕捉了

    1、页面不存在的时候,找不到对应的Controller,那没有任何Controller被执行,所以自然也不会捕捉到错误了

    2、在 IAuthorizationFilter 下发生错误的时候,错误捕捉代码在IExceptionFilter中,而IAuthorizationFilter的优先权高于IExceptionFilter,所以也就捕捉不到了

    那有没有别的方法?参考了一个老外的代码,发现了一种完美的方法

    protected void Application_Error(object sender, EventArgs e)
    {

    Exception exception
    = Server.GetLastError();

    Response.Clear();


    HttpException httpException
    = exception as HttpException;
    RouteData routeData
    = new RouteData();
    routeData.Values.Add(
    "controller", "Error");

    if (httpException == null)
    {
    routeData.Values.Add(
    "action", "Index");
    }
    else //It's an Http Exception, Let's handle it.
    {

    switch (httpException.GetHttpCode())
    {
    case 404:
    // Page not found.
    routeData.Values.Add("action", "HttpError404");
    break;
    case 500:
    // Server error.
    routeData.Values.Add("action", "HttpError500");
    break;
    // Here you can handle Views to other error codes.
    // I choose a General error template
    default:
    routeData.Values.Add(
    "action", "General");
    break;
    }
    }

    // Pass exception details to the target error View.
    routeData.Values.Add("error", exception.Message);

    // Clear the error on server.
    Server.ClearError();

    // Call target Controller and pass the routeData.
    IController errorController = new WEB.Controllers.ErrorController();
    errorController.Execute(
    new RequestContext(
    new HttpContextWrapper(Context), routeData));

    }

    把这段代码放到 Global.asax 中,并且新建一个 Controller 叫做 Error

    namespace WEB.Controllers
    {
    public class ErrorController : Controller
    {
    public ActionResult Index(string error)
    {
    ViewData[
    "Title"] = "WebSite 网站内部错误";
    ViewData[
    "Description"] = error;
    return View("Index");
    }

    public ActionResult HttpError404(string error)
    {
    ViewData[
    "Title"] = "HTTP 404- 无法找到文件";
    ViewData[
    "Description"] = error;
    return View("Index");
    }

    public ActionResult HttpError500(string error)
    {
    ViewData[
    "Title"] = "HTTP 500 - 内部服务器错误";
    ViewData[
    "Description"] = error;
    return View("Index");
    }


    public ActionResult General(string error)
    {
    ViewData[
    "Title"] = "HTTP 发生错误";
    ViewData[
    "Description"] = error;
    return View("Index");
    }
    }
    }
    这样,就可以捕捉所有错误了。

    但其实,这样也不是完美的,因为如果你参考了我第一个问题中,在IIS6下不修改IIS设置,运行了MVC,那当后缀名不是.aspx的时候,错误不会被捕捉

    因为这时候输入的地址根本没有交给网站来处理,IIS直接抛出了错误,因为IIS认为这个后缀名不是你所能执行的

    暂时先到这里,也许会有第二部分……

    如有错误,或者有疑问,可以直接留言,我会及时答复

    或者发我邮箱:dozer@dozer.net.cn

    原文地址:http://www.cnblogs.com/dozer/archive/2010/04/08/1706879.html

  • 相关阅读:
    第九周学习报告
    人月神话阅读笔记02
    数组 分步 详细
    第八周学习总结
    课堂练习
    学习进度报告09
    用户模板和用户场景
    学习进度报告08
    课堂随笔
    学习进度报告07
  • 原文地址:https://www.cnblogs.com/fcsh820/p/1707538.html
Copyright © 2011-2022 走看看