控制器介绍

系统 1472 0

新建立MVC3项目,名为12-1ControllersAndActions,使用空模板。

Global.asax中默认的路由定义为:

      
        public
      
      
        static
      
      
        void
      
      
         RegisterRoutes(RouteCollection routes)

        {

            routes.IgnoreRoute(
      
      
        "
      
      
        {resource}.axd/{*pathInfo}
      
      
        "
      
      
        );



            routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
      , id = UrlParameter.Optional } 
      
        //
      
      
         Parameter defaults
      
      
                    );



        }
      
    

一、两种方法实现自己的控制器

1、用IController创建控制器

在MVC框架中,控制器类必须实现System.Web.Mvc命名空间的IController接口。

System.Web.Mvc.IController接口如下所示:

      
        public
      
      
        interface
      
      
         IController

{

    
      
      
        void
      
      
         Execute(RequestContext requestContext);

}
      
    

接口只有一个方法Execute,在请求目标控制器时将被调用。

通过实现IController,就可以创建控制器类,但这是一个相当低级的接口,要做大量工作才能让自己创建的控制器有效,下面只是一个简单的演示。

鼠标右击项目中的Controllers文件夹,选择 Add -> Class,创建新类,取名为BasicController,代码如下:

      
        namespace
      
      
         _12_1ControllersAndActions.Controllers

{

    
      
      
        public
      
      
        class
      
      
         BasicController:IController

    {

        
      
      
        public
      
      
        void
      
      
         Execute(RequestContext requestContext)

        {

            
      
      
        string
      
       controller = (
      
        string
      
      )requestContext.RouteData.Values[
      
        "
      
      
        controller
      
      
        "
      
      
        ];

            
      
      
        string
      
       action = (
      
        string
      
      )requestContext.RouteData.Values[
      
        "
      
      
        action
      
      
        "
      
      
        ];

            requestContext.HttpContext.Response.Write(

                
      
      
        string
      
      .Format(
      
        "
      
      
        Controller:{0}, Action:{1}
      
      
        "
      
      
        , controller, action));

        }

    }

}
      
    

 如果运行程序,导航到"~/Basic/Index",根据路由定义,也可以导航到"~/Basic",产生的结果为:

Controller:Basic,Action:Index

 

2、一般的做法是创建派生于Controller类的控制器

鼠标右击项目中的Controllers文件夹,选择 Add -> Controller,新建控制器,命名为DerivedController,代码如下:

      
        namespace
      
      
         _12_1ControllersAndActions.Controllers

{

    
      
      
        public
      
      
        class
      
      
         DerivedController : Controller

    {

        
      
      
        //
      
      
        //
      
      
         GET: /Derived/
      
      
        public
      
      
         ActionResult Index()

        {

            ViewBag.Message 
      
      = 
      
        "
      
      
        Hello from the DerivedController Index method.
      
      
        "
      
      
        ;

            
      
      
        return
      
       View(
      
        "
      
      
        MyView
      
      
        "
      
      
        );

        }



    }

}
      
    

在方法Index上鼠标右键,添加视图,视图取名为MyView

/Views/Derived/MyView.cshtml

      
        @{

    ViewBag.Title = "MyView";

}




      
      
        <
      
      
        h2
      
      
        >
      
      MyView
      
        </
      
      
        h2
      
      
        >
      
      
        <
      
      
        h1
      
      
        >
      
      Message: @ViewBag.Message
      
        </
      
      
        h1
      
      
        >
      
    

 运行程序,导航到"~/Derived/Index",或者根据路由定义,也可以导航到"~/Derived",产生的结果为:

MyView

Message:Hello from the DerivedController Index method.

 

二、控制器接收输入

控制器常常需要访问输入数据,也就是在请求控制器的动作方法时传递进来的输入数据,如查询字符串值(指url尾部带问号?后面跟的部分,称为url的查询字符串)、表单值、以及路由系统根据输入url解析所得到的参数。

访问这些数据有三种方式:

通过上下文对象(Context Objects)获取数据。

通过参数传递给动作方法。

使用模型绑定(Model Binding)。

这里主要讨论前两种,模型绑定在后面讨论。

1、通过上下文对象获取数据

访问上下文对象,通过使用一组便利属性(Convenience Property)来进行访问。所谓上下文对象,实际上就是访问的与请求相关的信息。

如果要使用便利属性来访问与请求相关的信息,要注意一点,就是只能在派生于Controller的自定义控制器中才能使用。即,如果是通过实现IController接口来完成的自定义控制器里面不能使用这些便利属性。这些便利属性包括Request、Response、RouteData、HttpContext、Server等,每个属性都包含了请求不同方面的信息。见p305,表12-1。

(1)下面通过一个例子来表现这种通过上下文对象获取数据的方式。

在12-1ControllersAndActions项目中,HomeController控制器定义如下:

      
        namespace
      
      
         _12_1ControllersAndActions.Controllers

{

    
      
      
        public
      
      
        class
      
      
         HomeController : Controller

    {

        
      
      
        public
      
      
         ActionResult Index()

        {

            
      
      
        //
      
      
        访问上下文对象的各个属性
      
      
        string
      
       userName =
      
         User.Identity.Name;

            
      
      
        string
      
       serverName =
      
         Server.MachineName;

            
      
      
        string
      
       clientIP =
      
         Request.UserHostAddress;

            DateTime dateStamp 
      
      =
      
         HttpContext.Timestamp;

            ViewBag.userName 
      
      =
      
         userName;

            ViewBag.serverName 
      
      =
      
         serverName;

            ViewBag.clientIP 
      
      =
      
         clientIP;

            ViewBag.dateStamp 
      
      =
      
         dateStamp;

            
      
      
        //
      
      
        接收Request.Form所递交的数据

            
      
      
        //
      
      
        string oldProductName = Request.Form["OldName"];

            
      
      
        //
      
      
        string newProductName = Request.Form["NewName"];
      
      
        return
      
      
         View();

        }



    }

}
      
    

 

/Views/Home/Index.cshtml内容如下:

      
        @{

    ViewBag.Title 
      
      = 
      
        "
      
      
        Index
      
      
        "
      
      
        ;

}




      
      <h2>Index</h2>

<h2>userName=@ViewBag.userName</h2>

<h2>serverName=@ViewBag.serverName</h2>

<h2>clientIP=@ViewBag.clientIP</h2>

<h2>dataStamp=@ViewBag.dateStamp</h2>
    

这里可以注意,如果希望显示出一些上下文数据,而又不想有对应的cshtml文件,那么可以用response.write,例如:

      
        namespace
      
      
         _12_1ControllersAndActions.Controllers

{

    
      
      
        public
      
      
        class
      
      
         HomeController : Controller

    {

        
      
      
        public
      
      
         ActionResult Index()

        {

            
      
      
        //
      
      
        访问上下文对象的各个属性
      
      
        string
      
       userName =
      
         User.Identity.Name;

            
      
      
        string
      
       serverName =
      
         Server.MachineName;

            
      
      
        string
      
       clientIP =
      
         Request.UserHostAddress;

            DateTime dateStamp 
      
      =
      
         HttpContext.Timestamp;

            ViewBag.userName 
      
      =
      
         userName;

            ViewBag.serverName 
      
      =
      
         serverName;

            ViewBag.clientIP 
      
      =
      
         clientIP;

            ViewBag.dateStamp 
      
      =
      
         dateStamp;

            
      
      
        //
      
      
        接收Request.Form所递交的数据

            
      
      
        //
      
      
        string oldProductName = Request.Form["OldName"];

            
      
      
        //
      
      
        string newProductName = Request.Form["NewName"];
      
      
        return
      
      
         View();

        }



        
      
      
        public
      
      
        void
      
      
         Index2()

        {

            
      
      
        //
      
      
        访问上下文对象的各个属性
      
      
        string
      
       userName =
      
         User.Identity.Name;

            
      
      
        string
      
       serverName =
      
         Server.MachineName;

            
      
      
        string
      
       clientIP =
      
         Request.UserHostAddress;

            DateTime dateStamp 
      
      =
      
         HttpContext.Timestamp;

            Response.Write(
      
      
        string
      
      .Format(
      
        "
      
      
        userName:{0}<br>serverName:{1}<br>clientIP:{2}<br>dataStamp:{3}
      
      
        "
      
      
        , 

                userName, serverName, clientIP, dateStamp));

        }



    }

}
      
    

这里的Index2就没有对应的cshtml文件对应。程序运行后,输入地址:"~/Home/Index2"就可以查看到用Response.Write写出的内容。

 

 上下文对象常用的有Request.QueryString、Request.Form和RouteData.Values

(2)通过上下文对象访问RouteData.Values的例子

上面例子中的项目12-1ControllersAndActions,在HomeController控制器中添加了一个TestInput动作方法,如下:

      
        namespace
      
      
         _12_1ControllersAndActions.Controllers

{

    
      
      
        public
      
      
        class
      
      
         HomeController : Controller

    {

        
      
      
        public
      
      
         ActionResult Index()

        {

            
      
      
        //
      
      
        访问上下文对象的各个属性
      
      
        string
      
       userName =
      
         User.Identity.Name;

            
      
      
        string
      
       serverName =
      
         Server.MachineName;

            
      
      
        string
      
       clientIP =
      
         Request.UserHostAddress;

            DateTime dateStamp 
      
      =
      
         HttpContext.Timestamp;

            ViewBag.userName 
      
      =
      
         userName;

            ViewBag.serverName 
      
      =
      
         serverName;

            ViewBag.clientIP 
      
      =
      
         clientIP;

            ViewBag.dateStamp 
      
      =
      
         dateStamp;

            
      
      
        //
      
      
        接收Request.Form所递交的数据

            
      
      
        //
      
      
        string oldProductName = Request.Form["OldName"];

            
      
      
        //
      
      
        string newProductName = Request.Form["NewName"];
      
      
        return
      
      
         View();

        }



        
      
      
        public
      
      
        void
      
      
         Index2()

        {

            
      
      
        //
      
      
        访问上下文对象的各个属性
      
      
        string
      
       userName =
      
         User.Identity.Name;

            
      
      
        string
      
       serverName =
      
         Server.MachineName;

            
      
      
        string
      
       clientIP =
      
         Request.UserHostAddress;

            DateTime dateStamp 
      
      =
      
         HttpContext.Timestamp;

            Response.Write(
      
      
        string
      
      .Format(
      
        "
      
      
        userName:{0}<br>serverName:{1}<br>clientIP:{2}<br>dataStamp:{3}
      
      
        "
      
      
        , 

                userName, serverName, clientIP, dateStamp));

        }



        
      
      
        public
      
      
        void
      
      
         TestInput()

        {

            
      
      
        string
      
       inputController = (
      
        string
      
      )RouteData.Values[
      
        "
      
      
        controller
      
      
        "
      
      
        ];

            
      
      
        string
      
       inputAction = (
      
        string
      
      )RouteData.Values[
      
        "
      
      
        action
      
      
        "
      
      
        ];

            
      
      
        int
      
       inputId = Convert.ToInt32(RouteData.Values[
      
        "
      
      
        id
      
      
        "
      
      
        ]);

            Response.Write(
      
      
        string
      
      .Format(
      
        "
      
      
        inputController={0}<br>inputAction={1}<br>inputId={2}
      
      
        "
      
      
        ,

                inputController, inputAction, inputId));

        }



    }

}
      
    

在TestInput动作方法中,通过RouteData.Values["controller"]读取到当前请求的控制器名字,通过RouteData.Values["action"]读取到当前请求的动作方法的名字,通过RouteData.Values["id"]访问到当前请求中的 URL里对应到路由中的自定义变量id的值读取出来。那么这里RouteData.Values中的controller、action、id属性来自于哪里,RouteData.Values中还有哪些属性可用,就取决于在Global.asax中的路由定义。

先看一下为当前这个例子设计的路由定义:

      
        public
      
      
        static
      
      
        void
      
      
         RegisterRoutes(RouteCollection routes)

        {

            routes.IgnoreRoute(
      
      
        "
      
      
        {resource}.axd/{*pathInfo}
      
      
        "
      
      
        );



            
      
      
        //
      
      
        这是本身的默认路由,现在需要如果有id要限定它只能是数字,用正则表达式

            
      
      
        //
      
      
        routes.MapRoute(

            
      
      
        //
      
      
            "Default", 
      
      
        //
      
      
         Route name

            
      
      
        //
      
      
            "{controller}/{action}/{id}", 
      
      
        //
      
      
         URL with parameters

            
      
      
        //
      
      
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
      
      
        //
      
      
         Parameter defaults

            
      
      
        //
      
      
        );
      
      
        

            routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       } 
      
        //
      
      
         Parameter defaults
      
      
                    );



            routes.MapRoute(

                
      
      
        "
      
      
        Default2
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       }, 
      
        //
      
      
         Parameter defaults
      
      
        new
      
       { id=
      
        @"
      
      
        \d+
      
      
        "
      
      
        }

            );

        }
      
    

现在这个例子,希望路由在原来的默认路由的基础上增加一个约束,就是如果url中输入了id,那么希望将id的值约束在数字上,如果id输入的是非数字的值,比如字母之类就不能匹配路由。

用正则表达式加约束条件,生成匿名对象new { id=@"\d+" },但是这个约束不能直接加在原来的默认路由上,原来的默认路由为:

      
                    routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
      , id = UrlParameter.Optional } 
      
        //
      
      
         Parameter defaults
      
      

            );
    

在这个默认路由中,定义了url模式里的变量有3个,分别是controller、action和id,并用new设置了这三个变量的默认参数值,其中id设置的是UrlParameter.Optional,设置为这个值,表示在匹配url时,id可以有也可以没有,如果没有id,那么就没有id这个变量。如果希望有id的时候把它的值限定在数字上,不能直接在参数默认值的后面添加约束,比如:

      
                    routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
      , id = UrlParameter.Optional }, 
      
        //
      
      
         Parameter defaults
      
      
        new
      
       { id=
      
        @"
      
      
        \d+
      
      
        "
      
      
        }

            );
      
    

加上这个约束,就表示id必须要有值,而且要是数字,否则就不匹配。这样一来,下面的url都不能再匹配了:

"~/"

"~/Home/Index"

"~/Home/TestInput"

也就是说id=UrlParameter.Optional就失去了意义。

解决方法就是把路由定义成两个:

      
                routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       } 
      
        //
      
      
         Parameter defaults
      
      
                    );



            routes.MapRoute(

                
      
      
        "
      
      
        Default2
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       }, 
      
        //
      
      
         Parameter defaults
      
      
        new
      
       { id=
      
        @"
      
      
        \d+
      
      
        "
      
      }
      
);

按照顺序依次匹配,没有写id的匹配第一个路由定义,写了id的匹配第二个路由定义。

那么没有写id的时候,匹配第一个路由定义,就是{controller}/{action},就只有controller和action两个变量,这个时候在动作方法中访问RouteData.Values["id"]得到的结果就为null,但是这里的类型转换用的是Convert.ToInt32(),当括号内的对象为null时,得到的结果就为0。如果用的是int.Parse()遇到这种情况就会抛出异常。

int inputId = Convert.ToInt32(RouteData.Values["id"]);

当然,如果取到id的值,如果只想要字符类型,那就不用这么复杂, 可以直接用

string inputId = (string)RouteData.Values["id"];

 

对于本例,如果在url中输入的是"~/Home/TestInput/325",那么显示的结果为:

inputController=Home
inputAction=TestInput
inputId=325

 

(3)通过上下文对象访问Request.QueryString的例子

Request.QueryString查询字符串就是跟在url后面带问号之后的内容。例如:

http://localhost:1943/Home/TestInput2?var1=abc&var2=123

问号后面的var1=abc&var2=123就是QueryString。

 

例,假设跟上一个例题同样的路由定义:

      
        public
      
      
        static
      
      
        void
      
      
         RegisterRoutes(RouteCollection routes)

        {

            routes.IgnoreRoute(
      
      
        "
      
      
        {resource}.axd/{*pathInfo}
      
      
        "
      
      
        );



            
      
      
        //
      
      
        这是本身的默认路由,现在需要如果有id要限定它只能是数字,用正则表达式

            
      
      
        //
      
      
        routes.MapRoute(

            
      
      
        //
      
      
            "Default", 
      
      
        //
      
      
         Route name

            
      
      
        //
      
      
            "{controller}/{action}/{id}", 
      
      
        //
      
      
         URL with parameters

            
      
      
        //
      
      
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
      
      
        //
      
      
         Parameter defaults

            
      
      
        //
      
      
        );
      
      
        

            routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       } 
      
        //
      
      
         Parameter defaults
      
      
                    );



            routes.MapRoute(

                
      
      
        "
      
      
        Default2
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       }, 
      
        //
      
      
         Parameter defaults
      
      
        new
      
       { id=
      
        @"
      
      
        \d+
      
      
        "
      
      
        }

            );

        }
      
    

 

在HomeController中新增了名为TestInput2的动作方法:

      
                public
      
      
        void
      
      
         TestInput2()

        {

            
      
      
        string
      
       inputController = (
      
        string
      
      )RouteData.Values[
      
        "
      
      
        controller
      
      
        "
      
      
        ];

            
      
      
        string
      
       inputAction = (
      
        string
      
      )RouteData.Values[
      
        "
      
      
        action
      
      
        "
      
      
        ];

            
      
      
        int
      
       inputId = Convert.ToInt32(RouteData.Values[
      
        "
      
      
        id
      
      
        "
      
      
        ]);

            
      
      
        string
      
       queryVar1 = Request.QueryString[
      
        "
      
      
        var1
      
      
        "
      
      
        ];

            
      
      
        string
      
       queryVar2 = Request.QueryString[
      
        "
      
      
        var2
      
      
        "
      
      
        ];

            Response.Write(
      
      
        string
      
      .Format(
      
        "
      
      
        inputController={0}<br>inputAction={1}<br>
      
      
        "
      
       + 

                
      
        "
      
      
        inputId={2}<br>queryVar1={3}<br>queryVar2={4}
      
      
        "
      
      
        ,

                inputController, inputAction, inputId, queryVar1, queryVar2));

        }
      
    

这里用了两句话

string queryVar1 = Request.QueryString["var1"];
string queryVar2 = Request.QueryString["var2"];

来读取查询字符串中变量的值。

如果输入的url是"~/Home/TestInput2?var1=abc&var2=123"则显示的结果为:

inputController=Home
inputAction=TestInput2
inputId=0
queryVar1=abc
queryVar2=123

这个输入的url,没有匹配id,所以RouteData.Values["id"]为空,经过Convert.ToInt32()转换后值为0。QueryString里如果有多个变量,之间用符号&间隔。

 

扩充下这个例题,现在假设在/Views/Home/Index.cshtml,也就是HomeController中Index产生的视图上添加:

@Html.ActionLink("Navigate", "TestInput2", new { id="123" })

这时,如果路由定义为:

      
                    routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
      , id = UrlParameter.Optional } 
      
        //
      
      
         Parameter defaults
      
      

            );
    

那么ActionLink产生的html为:

<a href="/Home/TestInput2/123">Navigate</a>

点击该超链接后显示的结果为:

inputController=Home
inputAction=TestInput2
inputId=123
queryVar1=
queryVar2=

 

但是,如果路由定义为:

      
                    routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       } 
      
        //
      
      
         Parameter defaults
      
      
                    );



            routes.MapRoute(

                
      
      
        "
      
      
        Default2
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       }, 
      
        //
      
      
         Parameter defaults
      
      
        new
      
       { id = 
      
        @"
      
      
        \d+
      
      
        "
      
      
         }

            );
      
    

那么@Html.ActionLink("Navigate", "TestInput2", new { id="123" })产生的html为:

<a href="/Home/TestInput2?id=123">Navigate</a>

这是因为按定义顺序,会首先去匹配第一个路由定义,那么反推回url。第一个路由定义中没有id,那就认为new { id="123" }产生的就是查询字符串。点击这个超链接后,产生的显示结果为:

inputController=Home
inputAction=TestInput2
inputId=0
queryVar1=
queryVar2=

 

这样一来,如果是第二种路由定义,既想生成的url中产生id,又有查询字符串,那就需要使用:

@Html.ActionLink("Navigate", "TestInput2/123", new { var1="ABC", var2="325" })

产生的html为:

<a href="/Home/TestInput2/123?var1=ABC&amp;var2=325">Navigate</a>

注意html中的&amp;就是&,最后产生的url就是"~/Home/TestInput2/123?var1=ABC&var2=325"

点击该超链接后,产生的显示结果为:

inputController=Home
inputAction=TestInput2
inputId=123
queryVar1=ABC
queryVar2=325

 

(4)通过上下文对象访问Request.Form中数据的例子

利用Request.Form可以读取提交过来的表单中的数据,通过Name的属性值来进行识别访问。下面构造一个例子来说明用Request.Form来读取表单数据的情况。

假设使用的路由定义为:

      
        public
      
      
        static
      
      
        void
      
      
         RegisterRoutes(RouteCollection routes)

        {

            routes.IgnoreRoute(
      
      
        "
      
      
        {resource}.axd/{*pathInfo}
      
      
        "
      
      
        );
      
      
        

            routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       } 
      
        //
      
      
         Parameter defaults
      
      
                    );



            routes.MapRoute(

                
      
      
        "
      
      
        Default2
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       }, 
      
        //
      
      
         Parameter defaults
      
      
        new
      
       { id = 
      
        @"
      
      
        \d+
      
      
        "
      
      
         }

            );

        }
      
    

在HomeController中添加了TestInput3()动作方法的两个重载版本:

      
                [HttpGet]

        
      
      
        public
      
      
         ViewResult TestInput3()

        {

            
      
      
        return
      
      
         View();

        }



        [HttpPost]

        
      
      
        public
      
       ViewResult TestInput3(
      
        string
      
      
         dummy)

        {

            
      
      
        string
      
       inputController = (
      
        string
      
      )RouteData.Values[
      
        "
      
      
        controller
      
      
        "
      
      
        ];

            
      
      
        string
      
       inputAction = (
      
        string
      
      )RouteData.Values[
      
        "
      
      
        action
      
      
        "
      
      
        ];

            
      
      
        int
      
       inputId = Convert.ToInt32(RouteData.Values[
      
        "
      
      
        id
      
      
        "
      
      
        ]);

            
      
      
        string
      
       city = Request.Form[
      
        "
      
      
        City
      
      
        "
      
      
        ];

            DateTime forDate 
      
      = DateTime.Parse(Request.Form[
      
        "
      
      
        forDate
      
      
        "
      
      
        ]);

            ViewBag.inputController 
      
      =
      
         inputController;

            ViewBag.inputAction 
      
      =
      
         inputAction;

            ViewBag.inputId 
      
      =
      
         inputId;

            ViewBag.city 
      
      =
      
         city;

            ViewBag.forDate 
      
      =
      
         forDate;

            
      
      
        return
      
       View(
      
        "
      
      
        TI3Result
      
      
        "
      
      
        );

        }
      
    

这里用了两个注解属性[HttpGet]和[HttpPost]来指定一个TestInput3用于Get请求,另一个TestInput3动作方法用于Post请求。在本例中,希望在Post请求的TestInput3动作方法中利用上下文对象Request.Form来访问表单数据,本部需要指定参数。但是同名的两个动作方法TestInput3看来是通过重载来实现的,如果名字相同,返回类型相同,参数又完全一致的话,程序就不能通过编译。所以,为了演示这个例子,就在Post请求的动作方法TestInput3上加了一个哑元参数dummy,目的就是为了完成同名的TestInput3函数的重载。

接下来,在由Get请求TestInput3时,返回的视图是默认视图/Views/Home/TestInput3.cshtml,在里面构造了表单:

      
        @{

    ViewBag.Title = "TestInput3";

}




      
      
        <
      
      
        h2
      
      
        >
      
      TestInput3
      
        </
      
      
        h2
      
      
        >
      
      
        

@using (Html.BeginForm())

{

    
      
      
        <
      
      
        p
      
      
        >
      
      city:
      
        <
      
      
        input 
      
      
        type
      
      
        ="text"
      
      
         name
      
      
        ="City"
      
      
        /></
      
      
        p
      
      
        >
      
      
        <
      
      
        p
      
      
        >
      
      forDate:
      
        <
      
      
        input 
      
      
        type
      
      
        ="text"
      
      
         name
      
      
        ="forDate"
      
      
        /></
      
      
        p
      
      
        >
      
      
        <
      
      
        input 
      
      
        type
      
      
        ="submit"
      
      
         value
      
      
        ="提交"
      
      
        />
      
      
           

}
      
    

表单由

@using (Html.BeginForm())

{

    ...

}

指定。里面有是三个元素,第一个是文本框,name为City,第二个也是文本框,name属性为forDate。Request.Form就依赖这些元素的name来识别和访问指定的元素值。第三个元素是按钮,类型为submit,按钮显示的文字为“提交”。点击该按钮后,默认将表单Post到与产生当前视图同名的动作方法上,本例子中,产生这个视图的动作方法是TestInput3,那么Post回去的时候,也就是传递给同名的TestInput3动作方法。

在响应Post的TestInput3动作方法通过:

string city = Request.Form["City"];
DateTime forDate = DateTime.Parse(Request.Form["forDate"]);

读取到表单中元素的值后,再利用ViewBag传递给显示结果的视图,该动作方法返回时指定了视图名return View("TI3Result").

那么,就在/Views/Home/TI3Result.cshtml中产生输出显示的结果。添加视图文件/Views/Home/TI3Result.cshtml如下:

      
        @{

    ViewBag.Title = "TI3Result";

}




      
      
        <
      
      
        h2
      
      
        >
      
      TI3Result
      
        </
      
      
        h2
      
      
        >
      
      
        <
      
      
        p
      
      
        >
      
      inputController=@ViewBag.inputController
      
        </
      
      
        p
      
      
        >
      
      
        <
      
      
        p
      
      
        >
      
      inputAction=@ViewBag.inputAction
      
        </
      
      
        p
      
      
        >
      
      
        <
      
      
        p
      
      
        >
      
      inpuId=@ViewBag.inputId
      
        </
      
      
        p
      
      
        >
      
      
        <
      
      
        p
      
      
        >
      
      city=@ViewBag.city
      
        </
      
      
        p
      
      
        >
      
      
        <
      
      
        p
      
      
        >
      
      forDate=@ViewBag.forDate
      
        </
      
      
        p
      
      
        >
      
    

执行程序后,在url上输入"~/Home/TestInput3,显示为:

控制器介绍

 在文本框中输入数据如下:

控制器介绍

点击提交按钮后,显示结果为:

控制器介绍

 

2、为动作方法设定参数传递数据

上下文对象常用的Request.QueryString、Request.Form和RouteData.Values等数据也可以通过动作方法的参数来设定。这里有个约定,就是参数名跟要访问的属性名或元素名同名,系统是根据名字自动去匹配。

(1)先看一个常规的例子,假设路由定义为:

      
                public
      
      
        static
      
      
        void
      
      
         RegisterRoutes(RouteCollection routes)

        {

            routes.IgnoreRoute(
      
      
        "
      
      
        {resource}.axd/{*pathInfo}
      
      
        "
      
      
        );
      
      
                    routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
      , id = UrlParameter.Optional } 
      
        //
      
      
         Parameter defaults
      
      
                    );
      
      

        }
    

在HomeController中新加了名为TestInput4()的动作方法:

      
                public
      
      
        void
      
       TestInput4(
      
        int
      
      
         id)

        {

            Response.Write(
      
      
        string
      
      .Format(
      
        "
      
      
        id={0}
      
      
        "
      
      
        , id));

        }
      
    

在动作方法TestInput()上设定了参数,整型的名为id的参数。动作方法的参数会用名字自动去匹配Request.QueryString、Request.Form和RouteData.Values中的属性和元素的值,依赖的就是名字。

接下来,在/Views/Home/Index.cshtml中添加ActionLink来生成超链接,指向HomeController中的TestInput4()动作方法。添加的代码为:

@Html.ActionLink("NavTestInput4", "TestInput4", new{ id=325 })

请注意ActionLink是怎么根据路由定义来生成html的。

第一个参数"NavTestInput4"是超链接文本,第二个参数是要访问的动作方法名字。没有给出控制器名字,则默认为产生当前视图页面的控制器,在本例子中就是Home控制器。第三个参数用new生成匿名对象,其中有id=325,根据路由定义,id匹配路由模式中的id变量。倒退回url,生成的超链接为:

      
        <
      
      
        a 
      
      
        href
      
      
        ="/Home/TestInput4/325"
      
      
        >
      
      NavTestInput4
      
        </
      
      
        a
      
      
        >
      
    

点击该超链接后,根据路由定义,匹配路由模式"{controller}/{action}/{id}",访问到Home控制器中的TestInput4动作方法,动作方法的参数id匹配路由模式中的{id},也就是RouteData.Values["id"]就通过匹配的动作方法参数id被传递到了动作方法中。而且可以看到,类型也自动匹配,参数中的int id,不需要做任何类型那个转换。显示结果为:

id=325

(2)跟上一个例题一样的路由定义,现在将HomeController中的TestInput4修改为:

      
                public
      
      
        void
      
       TestInput4(
      
        int
      
       id, 
      
        string
      
      
         var1)

        {

            Response.Write(
      
      
        string
      
      .Format(
      
        "
      
      
        id={0}<br>var1={1}
      
      
        "
      
      
        , id, var1));

        }
      
    

也就是说TestInput4的参数可以去匹配Request.QueryString、Request.Form和RouteData.Values等数据中的id和var1的值。将/Views/Home/Index.cshtml中ActionLink修改为:

@Html.ActionLink("NavTestInput4", "TestInput4", new{ id=325, var1="ABC" })

根据路由定义,在ActionLink中的第三个参数new{ id=325, var1="ABC" },id匹配路由模式"{controller}/{action}/{id}"中的{id},而var1在路由模式中没有变量叫这个名字,那就以问号?跟在url的最后面作为QueryString。本例子中的ActionLink产生的html为:

      
        <
      
      
        a 
      
      
        href
      
      
        ="/Home/TestInput4/325?var1=ABC"
      
      
        >
      
      NavTestInput4
      
        </
      
      
        a
      
      
        >
      
    

点击该超链接后,访问到Home控制器中的TestInput4动作方法。TestInput4动作方法中的参数id,接收RouteData.Values["id"]的值,参数var1接收Request.QueryString["var1"]的值。显示的结果为:

id=325
var1=ABC

(3)注意路由变化,如果将路由定义改为:

      
        public
      
      
        static
      
      
        void
      
      
         RegisterRoutes(RouteCollection routes)

        {

            routes.IgnoreRoute(
      
      
        "
      
      
        {resource}.axd/{*pathInfo}
      
      
        "
      
      
        );
      
      
        

            routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       } 
      
        //
      
      
         Parameter defaults
      
      
                    );



            routes.MapRoute(

                
      
      
        "
      
      
        Default2
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       }, 
      
        //
      
      
         Parameter defaults
      
      
        new
      
       { id = 
      
        @"
      
      
        \d+
      
      
        "
      
      
         }

            );

        }
      
    

假设HomeController中的动作方法TestInput4()与第(1)个例子中一样:

      
        public
      
      
        void
      
       TestInput4(
      
        int
      
      
         id)

        {

            Response.Write(
      
      
        string
      
      .Format(
      
        "
      
      
        id={0}
      
      
        "
      
      
        , id));

        }
      
    

在/Views/Home/Index.cshtml中的ActionLink也与第(1)个例子一样,代码为:

@Html.ActionLink("NavTestInput4", "TestInput4", new{ id=325 })

注意,由于路由的不同,这个例子中ActionLink生成html就与第(1)个例子不一样了。根据本例子中的路由定义,按照顺序,匹配第一个路由。在第一个路由中,路由的url模式为"{controller}/{action}",路由模式中没有id变量。那么ActionLink的第三个参数new{ id=325 }中的id就没有路由模式中的变量与其对应,就只能跟在问号后面,放在url的最后作为QueryString。所以,本例中生成的html为:

      
        <
      
      
        a 
      
      
        href
      
      
        ="/Home/TestInput4?id=325"
      
      
        >
      
      NavTestInput4
      
        </
      
      
        a
      
      
        >
      
    

需要注意的是,虽然产生的url不一样,但是在访问Home控制器里的TestInput4动作方法时,仍然可以让TestInput4的参数id正确读取到url中的id的值。这就是与前面直接通过上下文对象RouteData.Values["id"],或Request.QueryString["id"]来访问id值不一样的地方。动作方法TestInput4中的参数id,会自动去匹配Request.QueryString、Request.Form和RouteData.Values中与参数同名的数据。所以本例子中TestInput4的参数id,接收的是Request.QueryString["id"]的值,显示的结果为:

id=325

RouteData.Values和Request.QueryString中如果都有与动作方法的参数相同的变量,优先匹配的是RouteData.Values。例如,假设在Index.cshtml中的ActionLink代码为:

      @Html.ActionLink(
      
        "
      
      
        NavTestInput4
      
      
        "
      
      , 
      
        "
      
      
        TestInput4/123
      
      
        "
      
      , 
      
        new
      
      { id=
      
        325
      
       })
    

路由匹配本例子中的第二个路由定义,路由模式为"{controller}/{action}/{id}",产生的html为:

      
        <
      
      
        a 
      
      
        href
      
      
        ="/Home/TestInput4/123?id=325"
      
      
        >
      
      NavTestInput4
      
        </
      
      
        a
      
      
        >
      
    

根据匹配的第二个路由,这里既有RouteData.Values["id"]值为123,又有Request.QueryString["id"]值为325,传递给Home控制器的动作方法TestInput4的时候,TestInput4的参数id优先接收RouteData.Values["id"],显示结果为:

id=123

(4)提交的表单,Request.Form中各元素的值也可以通过动作方法的参数传递。

例如,前面TestInput3的例子,其他不变,将HomeController中接收Post请求的TestInput3动作方法修改为:

      
                [HttpPost]

        
      
      
        public
      
       ViewResult TestInput3(
      
        string
      
       controller, 
      
        string
      
      
         action,

            
      
      
        string
      
       city, DateTime forDate, 
      
        int
      
       id = 
      
        0
      
      
        )

        {

            
      
      
        string
      
       inputController =
      
         controller;

            
      
      
        string
      
       inputAction =
      
         action;

            
      
      
        int
      
       inputId =
      
         id;
      
      
        

            

            ViewBag.inputController 
      
      =
      
         inputController;

            ViewBag.inputAction 
      
      =
      
         inputAction;

            ViewBag.inputId 
      
      =
      
         inputId;

            ViewBag.city 
      
      =
      
         city;

            ViewBag.forDate 
      
      =
      
         forDate;

            
      
      
        return
      
       View(
      
        "
      
      
        TI3Result
      
      
        "
      
      
        );

        }
      
    

效果跟上一个TestInput3的例子一样。而且forDate的类型自动就给转换为DateTime类型。

 

三、从控制器产生输出

1、不要视图,直接用Response.Write输出

只要是派生于Controller的类里面的动作方法,就可以直接用Response.Write().

例如,前面的例子Index2()

      
        namespace
      
      
         _12_1ControllersAndActions.Controllers

{

    
      
      
        public
      
      
        class
      
      
         HomeController : Controller

    {
      
      
        public
      
      
        void
      
      
         Index2()

        {

            
      
      
        //
      
      
        访问上下文对象的各个属性
      
      
        string
      
       userName =
      
         User.Identity.Name;

            
      
      
        string
      
       serverName =
      
         Server.MachineName;

            
      
      
        string
      
       clientIP =
      
         Request.UserHostAddress;

            DateTime dateStamp 
      
      =
      
         HttpContext.Timestamp;

            Response.Write(
      
      
        string
      
      .Format(
      
        "
      
      
        userName:{0}<br>serverName:{1}<br>clientIP:{2}<br>dataStamp:{3}
      
      
        "
      
      
        , 

                userName, serverName, clientIP, dateStamp));

        }
      
      
        

    }

}
      
    

以及直接用Response.Redirect("/Some/Other/Url")也是属于这一种。

例如,在HomeController中添加动作方法TestRe

      
        public
      
      
        void
      
      
         TestRe()

        {

            Response.Redirect(
      
      
        "
      
      
        /Home/Index
      
      
        "
      
      
        );

        }
      
    

执行后,若输入"~/Home/TestRe",则会自动转移到"~/Home/Index"

 

2、理解Action Result

在动作方法中不直接使用Response对象,而是返回一个派生于ActionResult类的对象,它描述控制器要完成的操作,例如产生一个视图、重定向到另一个url或动作方法等。

不同的操作用不同的派生类,它们都是ActionResult的派生类。例如,重定向:

      
        public
      
      
         ActionResult TestRe()

        {

            
      
      
        return
      
      
        new
      
       RedirectResult(
      
        "
      
      
        /Home/Index
      
      
        "
      
      
        );

        }
      
    

结果就返回RedirectResult的一个对象,因为RedirectResult派生于ActionResult,所以动作方法的返回类型可以用ActionResult,当然也可以明确使用RedirectResult作为该动作方法的返回类型。另外,各派生类也有一些控制器辅助器方法,可以简化调用,例如RedirectResult类有辅助器方法Redirect

      
        public
      
      
         ActionResult TestRe()

        {

            
      
      
        return
      
       Redirect(
      
        "
      
      
        /Home/Index
      
      
        "
      
      
        );

        }
      
    

跟上面直接使用return new RedirectResult("/Home/Index");产生的效果是一样的。

各个常用的派生类和用到的控制器辅助方法见p313。

 

3、从动作方法中产生视图作为输出

      
            public
      
      
        class
      
      
         HomeController : Controller

    {

        
      
      
        public
      
      
         ViewResult Index()

        {
      
      
        return
      
      
         View();

        }
        
}

产生视图 /Views/Home/Index.cshtml

再如

      
        public
      
      
        class
      
      
         HomeController : Controller

    {

        
      
      
        public
      
      
         ViewResult Index()

        {

            
      
      
        return
      
       View(
      
        "
      
      
        HomePage
      
      
        "
      
      
        );

        }

    }
      
    

产生的视图为 /Views/Home/HomePage.cshtml

return View("HomePage")参数里加上双引号,表示给出指定的视图名。就不是默认跟动作方法同名的视图了。

另外,这里动作方法的返回类型用的是ViewResult,因为在知道方法返回的类型时,倾向于使用具体的类型,当然直接使用ActionResult也可以的。MVC框架在搜索视图时,先搜索Areas再搜索Views。仅以cshtml为例,下面是搜索顺序:

/Areas/<AreaName>/Views/<ControllerName>/视图名.cshtml

/Areas/<AreaName>/Views/Shared/视图名.cshtml

/Views/<ControllerName>/视图名.cshtml

/Views/Shared/视图名.cshtml

 

视图文件在生成html时会用到/Views/Shared/_Layout.cshtml布局文件作为默认布局文件,如果要用另一个布局文件可以用 

      
        return
      
       View(
      
        "
      
      
        HomePage
      
      
        "
      
      , 
      
        "
      
      
        _OtherLayout);
      
    

 当然,先要保证这个布局文件在/Views/Shared/目录中,也就是/Views/Shared/_OtherLayout.cshtml

 

四、把数据从动作方法传递给视图

1、使用视图模型对象

@model 类型

在HomeController中添加动作方法VMO(),如下:

      
        public
      
      
         ViewResult VMO()

        {

            DateTime date 
      
      =
      
         DateTime.Now;

            
      
      
        return
      
      
         View(date);

        }
      
    

注意,这里的return View(date);参数里的date没有加双引号,这表示要传递给视图的数据,而不是指定要渲染的视图名,这里如果将date加上双引号,含义就变了,就表示该动作方法要产生一个名为date.cshtml的视图来进行显示。

这里使用return View(date);就表示把对象date传递到与当前动作方法同名的视图上,也就是/Views/Home/VMO.cshtml

      
        @model DateTime

@{

    ViewBag.Title 
      
      = 
      
        "
      
      
        VMO
      
      
        "
      
      
        ;

}




      
      <h2>VMO</h2>
      
        

the day 
      
      
        is
      
      :@Model.DayOfWeek
    

在开头指定模型类型时,要用小写的m,这里是@model DateTime。而在文中读取模型值时,要用大写的M,如这里的@Model.DayOfWeek.

刚才强调,在动作方法中,返回View带参数时,不要加双引号,才表示返回的数据对象。如果要直接返回字符串对象,就需要在前面加上(object)指明这是模型对象。

      
        public
      
      
         ViewResult VMO()

        {

            DateTime date 
      
      =
      
         DateTime.Now;

            
      
      
        return
      
       View((
      
        object
      
      )
      
        "
      
      
        hello, world.
      
      
        "
      
      
        );

        }
      
    

在VMO.cshtml中,就使用string来指定模型类型。

      
        @model string

@{

    ViewBag.Title = "VMO";

}




      
      
        <
      
      
        h2
      
      
        >
      
      VMO
      
        </
      
      
        h2
      
      
        >
      
      
        

the day is:@Model
      
    

2、使用ViewBag传递数据

ViewBag允许你在这个动态对象上定义任意属性,并在视图中访问它们 ,就相当于键/值对。

只是vs对它不提供智能感应支持。

 

3、执行重定向

(1)重定向到字面url

假设在HomeController中有动作方法TestRe

      
        public
      
      
         RedirectResult TestRe()

        {

            
      
      
        return
      
       Redirect(
      
        "
      
      
        /Home/Index
      
      
        "
      
      
        );

        }
      
    

当访问"~/Home/TestRe"时,就会重定向到"~/Home/Index"

(2)重定向到路由系统的url

在HomeController中,假设有前面例子中的动作方法TestInput2()

      
        public
      
      
        void
      
      
         TestInput2()

        {

            
      
      
        string
      
       inputController = (
      
        string
      
      )RouteData.Values[
      
        "
      
      
        controller
      
      
        "
      
      
        ];

            
      
      
        string
      
       inputAction = (
      
        string
      
      )RouteData.Values[
      
        "
      
      
        action
      
      
        "
      
      
        ];

            
      
      
        int
      
       inputId = Convert.ToInt32(RouteData.Values[
      
        "
      
      
        id
      
      
        "
      
      
        ]);

            
      
      
        string
      
       queryVar1 = Request.QueryString[
      
        "
      
      
        var1
      
      
        "
      
      
        ];

            
      
      
        string
      
       queryVar2 = Request.QueryString[
      
        "
      
      
        var2
      
      
        "
      
      
        ];

            Response.Write(
      
      
        string
      
      .Format(
      
        "
      
      
        inputController={0}<br>inputAction={1}<br>
      
      
        "
      
       + 

                
      
        "
      
      
        inputId={2}<br>queryVar1={3}<br>queryVar2={4}
      
      
        "
      
      
        ,

                inputController, inputAction, inputId, queryVar1, queryVar2));

        }
      
    

下面定义动作方法TestRe()来重定向到TestInput2()

      
        public
      
      
         RedirectToRouteResult TestRe()

        {

            
      
      
        return
      
       RedirectToRoute(
      
        new
      
      
        

            {

                Controller 
      
      = 
      
        "
      
      
        Home
      
      
        "
      
      
        ,

                Action 
      
      = 
      
        "
      
      
        TestInput2
      
      
        "
      
      
        ,

                id 
      
      = 
      
        "
      
      
        123
      
      
        "
      
      
        ,

                var1 
      
      = 
      
        "
      
      
        ABC
      
      
        "
      
      
        ,

                var2 
      
      = 
      
        "
      
      
        999
      
      
        "
      
      
        

            });

        }
      
    

执行程序后,当输入"~/Home/TestTe",将产生重定向。注意,产生的url取决于所使用的路由定义。如果路由定义为

      
                    routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
      , id = UrlParameter.Optional } 
      
        //
      
      
         Parameter defaults
      
      

            );
    

则重定向产生的url为

"~/Home/TestInput2/123?var1=ABC&var2=999"

但这个路由定义,如果没有加以处理,在id处如果输入的不是数字,那么将会抛出异常。

如果路由定义用的是下面的定义

      
                    routes.MapRoute(

                
      
      
        "
      
      
        Default
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       } 
      
        //
      
      
         Parameter defaults
      
      
                    );



            routes.MapRoute(

                
      
      
        "
      
      
        Default2
      
      
        "
      
      , 
      
        //
      
      
         Route name
      
      
        "
      
      
        {controller}/{action}/{id}
      
      
        "
      
      , 
      
        //
      
      
         URL with parameters
      
      
        new
      
       { controller = 
      
        "
      
      
        Home
      
      
        "
      
      , action = 
      
        "
      
      
        Index
      
      
        "
      
       }, 
      
        //
      
      
         Parameter defaults
      
      
        new
      
       { id = 
      
        @"
      
      
        \d+
      
      
        "
      
      
         }

            );
      
    

那么产生的重定向url为

"~/Home/TestInput2?id=123&var1=ABC&var2=999"

(3)重定向到一个动作方法

      
        public
      
      
         RedirectToRouteResult TestRe()

{

    
      
      
        return
      
       RedirectToAction(
      
        "
      
      
        TestInput2
      
      
        "
      
      
        );

}
      
    

 

      
        public
      
      
         RedirectToRouteResult TestRe()

{

    
      
      
        return
      
       RedirectToAction(
      
        "
      
      
        TestInput2
      
      
        "
      
      , 
      
        new
      
       { id=
      
        "
      
      
        123
      
      
        "
      
      , var1=
      
        "
      
      
        ABC
      
      
        "
      
      , var2=
      
        "
      
      
        999
      
      
        "
      
      
        });

}
      
    

 

      
        public
      
      
         RedirectToRouteResult TestRe()

{

    
      
      
        return
      
       RedirectToAction(
      
        "
      
      
        TestInput2
      
      
        "
      
      , 
      
        "
      
      
        Home
      
      
        "
      
      
        );

}
      
    

 

      
        public
      
      
         RedirectToRouteResult TestRe()

{

  
      
      
        return
      
       RedirectToAction(
      
        "
      
      
        TestInput2
      
      
        "
      
      , 
      
        "
      
      
        Home
      
      
        "
      
      , 
      
        new
      
       { id=
      
        "
      
      
        123
      
      
        "
      
      , var1=
      
        "
      
      
        ABC
      
      
        "
      
      , var2=
      
        "
      
      
        999
      
      
        "
      
      
        });

}
      
    

 

 4、返回文件及二进制数据

(1)返回文件

文件下载

      
        public
      
      
         FileResult TestFile()

        {

            
      
      
        string
      
       fPath = AppDomain.CurrentDomain.BaseDirectory + 
      
        "
      
      
        DownloadTest/
      
      
        "
      
      
        ;

            
      
      
        //
      
      
        string fileName = @"c:\log.txt";
      
      
        string
      
       fileName = fPath + 
      
        "
      
      
        log.txt
      
      
        "
      
      
        ;

            
      
      
        string
      
       contentType = 
      
        "
      
      
        text/plain
      
      
        "
      
      
        ;

            
      
      
        string
      
       downloadName = 
      
        "
      
      
        Test.txt
      
      
        "
      
      
        ;

            
      
      
        return
      
      
         File(fileName, contentType, downloadName);     

        }
      
    

这里的AppDomain.CurrentDomain.BaseDirectory表示读取到当前项目的根物理路径,末尾带反斜杠。要下载的文件log.txt放在根目录下的DownloadTest文件夹中。在出现另存为对话框的时候,下载名被改为Test.txt。

(2)发送字节数组

      
        public
      
      
         FileContentResult TestFile()

        {

            
      
      
        byte
      
      [] data = ... 
      
        //
      
      
        二进制内容
      
      
        return
      
       File(data, 
      
        "
      
      
        text/plain
      
      
        "
      
      , 
      
        "
      
      
        Test.txt
      
      
        "
      
      
        );

        }
      
    

(3)发送流内容

如果所处理的数据可以通过一个打开的System.IO.Stream进行操作,可以把这个流传递给File方法的一个重载版本。这个流得内容将被读取并发送给浏览器。

      
        public
      
      
         FileStreamResult TestFile()

        {

            Stream stream 
      
      = ... 
      
        //
      
      
        打开某种流
      
      
        return
      
       File(stream, 
      
        "
      
      
        text/html
      
      
        "
      
      
        );

        }
      
    

5、返回错误及http错误代码

(1)指定错误码

      
        public
      
      
         HttpStatusCodeResult StatusCode()

        {

            
      
      
        return
      
      
        new
      
       HttpStatusCodeResult(
      
        404
      
      , 
      
        "
      
      
        url cannot be serviced.
      
      
        "
      
      
        );

        }
      
    

 

(2)发送404错误

      
        public
      
      
         HttpStatusCodeResult StatusCode()

        {

            
      
      
        return
      
      
         HttpNotFound();

        }
      
    

 

(3)发送401错误

      
        public
      
      
         HttpStatusCodeResult StatusCode()

        {

            
      
      
        return
      
      
        new
      
      
         HttpUnauthorizedResult();

        }
      
    

 

 

-lyj

控制器介绍


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论