VS2012_MVC4入门例子、代码视图分离办法、需要注意的坑爹问题等_被坑后不断更新此贴,要转载的话,请使用链接,不要转载内容

因为此贴会不断更新,所以,要转载的话,请使用链接,不要转载内容。

---------------------------------------------

题外话:

用C#做网站,目前主要有两种模式:Asp.net网站,基于WebForm,和Mvc4 (mvc3、其他自定义框架就不谈了)。也就是做 xx.aspx页面,并且工具栏有一堆现成的.net服务器控件 和 html控件可用。浏览器直接访问 xx.aspx页面。

1.基于WebForm的:

  优点:1. 做小网站方便,现成控件直接拖动

           2. VS对aspx提供可视支持,可以像DW(DreamWare)那样看到代码的同时,能看到网页的样子。

  缺点:1.不容易实现代码与界面分离,因此程序员之间合作不方便,程序与美工合作也不方便,因此不利于做大型BS项目。

          2.面对定制的需求,不容易实现。因为现成的.net服务端控件,可定制性差。比如,客户说,这个按钮,要做成某个图案,甚至图案要能变化。这些要求,会超出.net服务端本身控件的能力范围,因此只能找别的解决方案。比如html控件,js控件,或flash控件等。

2.基于Mvc4 + Razor:

    缺点:1.可以混编的Razor页面,做小网站不方便,没有能直接拖动的控件(Mvc4里不仅仅可以创建Razor页面,也可以继续使用WebForm页面,这样就可以拖控件)。

            2.VS对Razor页面不提供可是支持,因此你只能写代码,没办法马上就看到网页的样子。比如运行后,才能看到网页的最终效果。

    优点:1.非常容易实现代码与界面分离,因为MVC4就是干这个事情的。因此利于大家合作,利于做大型BS项目。 

            2.Razor可以让html与程序的混编,变得非常优雅,就像PHP一样,可以直接在xx.php里混入程序代码与html/css/js代码。最后,Mvc4提供一种类似于php框架的开发方式,也有利于php程序员的加入。

            3.最重要的是,Mvc4工程同时支持Razor 与 WebForm!所以,能用Mvc4,尽量用。当然,有一些第三方控件,最好在Mvc4环境下测一下。对于服务器环境,也做一个mvc4例子,测一下。

 

---------------------------------------------

正文:

1.创建一个项目

  1.1 文件 -> 菜单 -> 新建项目 -> 已安装 -> 模板 -> Visual C# -> Web -> ASP.NET MVC 4 Web 应用程序

  1.2 选择“空” (空MVC项目)

 

2.创建首页。注意,按照业界规范,首页的名字,默认应该为Index,但这里为了说明问题,一律不用规范名字。假设首页名字为 MvcMain。

   2.1 对 解决方案资源管理器 -> Controllers 单击鼠标右键,选择 添加 -> 控制器

   2.2 控制器名称填“MvcMainController”。注意,这里有一个格式规范问题。控制器名称,一律严格按照 “网页URL节点名称 + Controller”方式来命名。

          比如 http://www.baidu.com/Node1/Node2,这里,Node1与Node2,就是网页URL节点名称。如果访问入口为: http://www.baidu.com/ABC/ ,则网页URL节点名称为ABC,因此控制器的名称为“ABCController”。

   2.3 该页面其他栏目不填,点“添加”。

         此时出现:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 namespace Mvc4Test2.Controllers
 8 {
 9     public class MvcMainController : Controller
10     {
11         //
12         // GET: /MvcMain/
13 
14         public ActionResult Index()
15         {
16             return View();
17         }
18 
19     }
20 }

      2.4 说明:

            2.4.1 Controller是URL的入口。如果这个项目被部署到 http://www.mvc.com/,则上面创建的这个控制器的URL为 http://www.mvc.com/MvcMain

            2.4.2 当浏览器访问 http://www.mvc.com/MvcMain 时,读取的是 public ActionResult Index() 这个方法。

            2.4.3 你可以添加一个方法:About() 与 MailMe(),这个控制器代码就变成了这个样子:

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 namespace Mvc4Test2.Controllers
 8 {
 9     public class MvcMainController : Controller
10     {
11         //
12         // GET: /MvcMain/
13 
14         public ActionResult Index()
15         {
16             return View();
17         }
18 
19         public ActionResult About()
20         {
21             return View();
22         }
23 
24         public ActionResult MailMe()
25         {
26             return View();
27         }
28     }
29 }

 

            2.4.4 此时,About的入口URL为 http://www.mvc.com/MvcMain/About/ ,MailMe的入口URL为:http://www.mvc.com/MvcMain/MailMe/ ,当浏览器访问这个URL时,实际上是上面这个控制器,执行相应的方法。

            2.4.5 既然执行的是方法,那就可以加参数。对于参数,刚好是 GET 格式:http://..../NodeName/?ValueName1=Value2&ValueName2=Value2,这个表达式拆开:

                     http://..../NodeName/  +  ?   +   ValueName1=Value2   +   &   +  ValueName2=Value2

                    意思是,访问http://..../NodeName/,并且给入两个参数,第一个参数名字为ValueName1,值为Value2;第二个参数名字为ValueName2,值为Value2。

                    为了快速说明问题,把控制器的 Index方法修改为:

1 public string Index(string arg_strValue, int arg_intValue = 2)
2 {
3     return "MvcMain Index:arg_strValue = [" + arg_strValue + "], arg_intValue = [" + arg_intValue.ToString() + "]";
4 }

                   然后按F5调试。此时,打开的应该是:http://localhost:随机端口号/ ,并且是一个错误页面。不慌,在这个URL后面添加“MvcMain/”,整个URL变成:http://localhost:3343/MvcMain/ ,就可以看到效果了。此时,参数还未赋值,使用的是默认值。注意,你应该观察到,参数为默认值的情况下,string为null,mvc没报错,说明它允许null的string作为参数值。但int就不行。如果把Index方法  public string Index(string arg_strValue, int arg_intValue = 2)
  改为 public string Index(string arg_strValue, int arg_intValue) ,不给入参数,则会报错。
                   现在,测试一下给入参数:  http://localhost:3343/MvcMain/?arg_strValue=1235&arg_intValue=999 ,看到效果没?

 

                     2.4.6 把Index方法恢复为:

1 public ActionResult Index()
2 {
3     return View();
4 }

 

 3.为控制器添加网页内容。由于控制器只是一个入口,因此需要添加网页内容View。

    3.1 对 解决方案资源管理器 -> Views 单击鼠标右键,选择  添加 -> 新建文件夹,这个文件夹名字,要与控制器的名字相对应。上文建立的控制器名字为 MvcMainController,它的名字就是MvcMain。所以,这个文件夹的名字也应该是MvcMain。如果你建立了一个控制器,名字是ABCController,则这个新建文件夹的名字应该为ABC。

    3.2 对这个 MvcMain 文件夹,单机鼠标右键,选择 添加 -> 新建项 -> MVC 4 视图页(Razor),下方的“名称(N):”填Index.cshtml。首先,为什么名字是Index?因为Index刚好对应控制器MvcMainController的Index方法。这个是一一对应关系。你可以为控制器的About方法和MailMe方法,建立 About.cshtml 和 MailMe.cshtml 的视图页。其次,为什么后缀为 .cshtml ?这是微软规定的。

    3.3 创建好Index.cshtml后,内容设置为:

 1 @{
 2     Layout = null;
 3 }
 4 
 5 <!DOCTYPE html>
 6 
 7 <html>
 8 <head>
 9     <meta name="viewport" content="width=device-width" />
10     <title></title>
11 </head>
12 <body>
13     <div>
14     这就是传说中的视图页。浏览器先通过URL访问控制器,然后控制器执行里面的Index方法,最后Index方法再执行与控制器同名的MvcMain文件夹内的,与控制器的Index方法同名的Index.cshtml.
15     </div>
16 </body>
17 </html>

    3.4 F5执行。URL还是填 http://localhost:随机端口号/MvcMain/ ,看到效果了吧。

    3.5 现在,在MvcMain文件夹下,按刚才步骤,创建About.cshtml 和 MailMe.cshtml。内容随便写。然后F5调试,访问 http://localhost:随机端口号/MvcMain/About/http://localhost:随机端口号/MvcMain/MailMe/ ,看到效果了吧?

 

4.最后一步,让这个控制器成为首页。刚才F5调试时,打开的是 http://localhost:随机端口号/ ,这个本来应该是首页,但出现的是一个错误页面。必须通过 http://localhost:随机端口号/MvcMain/ 才能打开这个页面。现在,我们希望让 http://localhost:随机端口号/ 直接跳转到这个页面。

    4.1 解决方案资源管理器 -> 工程 -> 展开App_Start文件夹 -> 鼠标左键双击 RouteConfig.cs

    4.2 在这个文件里,找到 controller = "Home", action = "Index"。把Home改成MvcMain就可以了。如果你有一个叫 ABCController的控制器,你也可以把 Home 改为 ABC。

    4.3 后面有一个action = "Index",你也可以把Index改为About或MailMe。

    4.4 现在F5试试, http://localhost:随机端口号/  这个URL,现在不是错误页面了吧?而是MvcMain的界面吧。

 

 

----------------------------------------------------------------------------------

开发说明:

1.Razor搞出了一堆名堂,什么母版页、布局页、分部页等完全没有存在的必要,把简单问题搞复杂了。Razor比aspx搞定了include和混编,这就足够了。 内容页(视图页) + include + Razor风格混编,已经搞定所有事情,PHP就是这么做的。

2.事实上,大家可以发现,Razor的母版页、布局页和分部页等,最后生成的都是cshtml后缀,说明他们是同一种东西。aspx至少还把内容页aspx和母版页Master用后缀给区分开了。

3.因此,只要掌握了Razor的@单语句,@{ 多语句 } 以及include指令(@RenderPage( page path ) )就可以了。什么模板啊,布局啊,自己就用命名 + 路径来区分开。

4.以上三点只是让大家清楚,这些概念并不是需要一定使用的。但是,VS搞出这些,规范了命名风格,所以,尽量使用它们来遵守这个命名约定,对于规范化开发还是有好处的。此点与上面3点矛盾。总的来说,微软把这些东西弄复杂,但却给出了命名规范。因此大家没必要特意去墨守成规这些概念,能用尽量用,以提高命名规范性,如果有自己的命名规范,不用也行。

 

 

 

----------------------------------------------------------------------------------

后续资料:(以下代码全部为简写)

1.Razor的控制器与视图传值

http://msdn.microsoft.com/zh-cn/library/dd394711(v=vs.100).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1

2.Razor利用Model,进行更方便的传值:

  2.1 建立一个Model,为Info:

       class Info

       {

            InfoID : int;

            InfoName : string;

       }

 

  2.2 控制器传给视图:

        2.2.1 控制器Controller:(参数Arg_info的作用,在后面给出)

1         public ActionResult Index(Info arg_info)
2         {
3             Info newInfo = new Info();
4             newInfo.InfoID = 2;
5             newInfo.InfoName = "newInfo : 2";
6             return View(newInfo);
7         }

     

          2.2.2 视图View:

 1 @model MvcTest.Models.Info
 2 
 3 @{
 4     Layout = null;
 5 }
 6 
 7 <!DOCTYPE html>
 8 
 9 <html>
10 <head>
11     <meta name="viewport" content="width=device-width" />
12     <title></title>
13 </head>
14 <body>
15     <div>
16         <form method="post" action="~/MvcMain/Index_ReceiveData1">
17             <p>
18                 <input type="text" name="InfoID" id="InfoID" value="@Model.InfoID" />
19             </p>
20 
21             <p>
22                 <textarea name="InfoName" id="InfoName" cols="45" rows="5">@Model.InfoName</textarea>
23             </p>
24 
25             <p>
26                 <input type="submit" name="WebUI_Name_Form_Btn_Submit" id="WebUI_ID_Form_Btn_Submit" value="提交 Form" />
27             </p>
28         </form>
29     </div>
30 </body>
31 </html>

        发现没,html控件的ID和Name,与Info类的属性的名字是一样的。这种高耦合,实现了方便性。WCF也是因为这种耦合,才让开发变得更方便。当然,耦合带来的缺点,我们也应该重视。

 


    2.3 视图View传回给控制器

 1 [HttpPost]
 2 public ActionResult Index_ReceiveData1(Info arg_info)
 3 {
 4     if (ModelState.IsValid)
 5     {
 6         int id = arg_info.InfoID;
 7         int name = arg_info.InfoName;
 8     }
 9     else
10     {
11          throw new Excetion(.....);
12      }
13     return RedirectToAction("Index", arg_info);//把这个东东传回index,当然,不传回,做别的事情也可以。如果传回,则控制器的这个方法就不需要些View视图了。
14 
15 }

 

 

-------------------------------------------------------------------------------------------------------

路径问题

    对于一个网站,令人讨厌的就是路径问题。由于MVC4的路由比较特殊,因此,网页与外码之外的所有资源文件,不要放在Controller、Models以及Views这几个特殊目录下。自己在工程目录下,另建一个Resource文件夹。Resource文件夹应该与Controller、Models以及Views目录为同一级。然后,可以把Resource里的结构,设置为与Views内部结构一致。

  比如:主页:

  ~/Views/Main/Index.cshtml

  主页的相关资源,最好是放在

  ~/Resource/Main/下面

  实例:

  工程 / Views / Main / LayoutPage_Index.cshtml 母版页

  工程 / Views / Main / Index.cshtml 主页的内容页

  然后,在 LayoutPage_Index.cshtml 里,使用 @RenderPage("~/Views/Main/Index.cshtml"); 来渲染 Index.cshtml 内容。

 

 

-------------------------------------------------------------------------------------------------------

Razor + C#混编问题

  1.在PHP中,在xx.php里,把一个php的字符串,输出为html的方法是:echo 'PHPStr'; 或 $phpStr = "PHPStr"; echo $phpStr;

     在Razor里,

    1.1 单行

        1.1.1 输出一个C# string变量(假设 string cSharpStr = "123"):@cSharpStr 这样就可以了

        1.1.2 输出一个C# 字符串:@("CSharpString") ,注意这个字符串外面要加括号。

   1.2 多行

        1.2.1 输出一个C# string变量:

                @{

                      string str = "123";

                     @str;//这样就在这个位置输出123了

                }

        1.2.2 输出一个C#字符串:

               同上,也是:

              @{

                   @("123");

                }

        1.2.3 直接嵌入HTML代码:

                @{

                        <div>

                           @("输出内容");

                       </div>

                   }

      对于html新手来说,需要注意的是,如果要输出的是用户输入的文本,并且用户会输入比如"<script>"这些会引起浏览器执行的代码,那在输出时就需要做html的Encode处理了(或Url的Encode处理)。

 

 

-------------------------------------------------------------------------------------------------------

要注意的坑爹问题 (虽然微软的东西用起来很方便,但基本上它的产品都有一些坑爹的小问题)

1. 混编时,Razor指令,一定要在前面加 "@",即使是在@的代码段里。

    比如:单独在Html代码里使用:

1 <p> @RenderPage("~/Views/Main/Index_Login_NotLogin.cshtml")</p>

 

    接着,在代码段里使用:

1 <p>
2  @{
3     //这里就是Razor代码段
4    int a = 0;
5     //使用Razor的RenderPage指令,依然要在前面加@,否则不起作用
6     @RenderPage("~/Views/Main/Index_Login_NotLogin.cshtml");
7 }
8 </p>

    Razor的指令有一堆,RenderXXX,Html.XXX,Url.XXX,等等...

 

3.Razor的自动推断功能有各种Bug,导致开发者不得不每次写稍微复杂的内容,都需要用 “@” + “大括号”的方式来使用。

 

4.在Razor开发环境下,不会有自动引用功能,因此需要手动using,或写明class的绝对路径。比如,如果XX是System.Object.XX,则需要手动写全System.Object.XX。

 

5.在Razor开发环境下,以下IDE功能变得残缺:

    5.1 自动完成

    5.2 自动提示

    5.3 自动格式化(自动格式化的对齐功能总是出问题)

 

6.如果Razor里的代码有错误,不会提示,也无法访问,也无法调试。只能通过在浏览器的地址栏,输入该View的绝对URL后(View对应的Controller的方法名字),才能看到报错页面,而且也无法调试。

 

posted on 2013-04-07 21:41  xxxteam  阅读(4802)  评论(0编辑  收藏  举报

导航