在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
书Adam The Definitive Guide to HTML5 Adam Applied ASP.NET 4 in Context and Pro ASP.NET 4
到此为止,我们已经学了为什么ASP.NET MVC框架会出现,认识了建筑和潜在的设计目标。我们已经做了一个很好的测试驱动的实际的电子商务应哟那个。现在是时候打开钩子,揭示框架机制的所有细节。 在本书的第二部分,我们关注细节。从揭示一个ASP.NET MVC程序的结构,和应用请求处理管道开始。接着关注每个特性个体,如routing,controller,action,MVC view系统,带有领域模型的MVC的工作方式。 在这部分的最后两张,我们会看到如何在MVC程序中使用AJAX和jQuery。 概述MVC项目 在我们探索指定MVC特性之前,要提供一些额外的环境上下文。本章我们概述ASP.NET MVC应用的结构和本质,包括默认项目结构和必须遵循的命名规范。 1 使用VS MVC项目模板 当创建一个新的MVC3项目,VS让你选择Empty,Internet Application,Internet Application。Empty项目模板,会创建相对较少的文件和路径,给你最小的结构。 在这个对话框上,可以使用HTML5,微软已经开始添加HTML5到VS。我们忽略了这个选项,MVC框架。 当使用Internet或Intranet应用模板,可以创建单元测试作为VS解决方案的一部分。这两个模板的不同之处在于身份认证机制。
MVC应用部署拷贝文件夹结构到web server。处于安全的原因,IIS不提供Web.config,bin,App_code,App_GlobalResources,App_LocalResources,App_WebReferences,App_Data,App_Browsers这些路径中的文件。IIS也会把.asax ,.ascx,.sitemap,.resx,.mdb,.mdf,.ldf,.csproj过滤掉。如果想要调整项目的结构,必须确保不在URLs中使用这些名字和扩展名。
除了/Areas,表中的其他项是核心ASP.NET平台,和MVC应用不是特别有关。 1.1 使用Internet和Intranet应用控制器 这两个模板都有HomeController,它可以渲染Home页面和About页面。这些页面使用默认布局生成。 Internet应用模板还包含AccountController,它允许访问者注册,登录。它使用表单身份验证,保持用户是否登录的轨迹。它使用ASP.NET核心会员设施,记录注册用户的列表。会员设施会在第一次有人尝试着注册或登录时,在/App_Data文件夹试着创建SQL Server Express基于数据库的文件。如果没有安装并且运行SQL Server,这样会在长时间停顿后失败。AccountController也有actions和views,可以让注册用户改变密码。Intranet Application模板省略AccountController,因为它期望使用Windows domain/Active Directory基础设施管理账户和密码。 1.2 理解MVC约定 在MVC项目中,有两种类型的约定。第一种只是建议你如何设置项目的结构。例如,它惯例地将JavaScript文件放在Scripts文件夹。这是其他MVC开发人员期待找到它的地方,也是VS为新MVC项目放置初始化JavaScript文件的地方。但是你可以重命名Scripts文件夹,甚至完全删除它,放置scripts到任何地方。这不会阻碍MVC框架运行。 另一个类型的约定来自约定大于配置的原理。这意味着不用明确配置controller和views的关联。只需要一个明确的controller名字就行了。 所有约定都能使用自定义视图引擎改变。 1.2.1 以下是控制器类的约定 Controller类的名字必须以Controller结尾,如ProductController。当从MVC route或HTML helper方法参照controller,需要制定名字的第一部分,如Product,DefaultControllerFactory类会自动在名字后附加Controller,并开始寻找controller类。可以通过创建自定义的IControllerFactory接口的实现,改变这个行为。 1.2.2 以下是视图的约定 视图和局部视图应该在它关联的控制器名字的文件夹下,如ProductController类的关联视图应在/View/Product文件夹下。 MVC框架期望action方法的默认视图,应以它的名字命名。例如,List action方法的关联视图应叫List.cshtml,如果使用ASPX视图引擎是List.aspx。 默认视图是用来当你在action方法中调用View方法,返回结果。
1 return View();
我们指定一个不同的视图,使用名字
1 return View("MyOtherView");
我们没有包含文件的扩展名,或视图的路径。MVC框架会试着找到这个视图,使用文件名和视图引擎的扩展名,默认是Razor和ASPX视图引擎。 当查找一个视图,MVC框架会查找控制器命名的文件夹,然后找/Views/Shared文件夹。这意味着我们可以在不同的controller中使用/View/Shared文件夹中的同一个view,并依赖框架找到他们。 1.2.3 以下是布局的约定 布局的命名约定,是在文件名前加_下划线前缀,这起源于WebMatrix,另一个使用Razor的。布局文件放在/Views/Shared文件夹。VS创建一个叫做_Layout.cshtml的布局,作为初始化项目模板的一部分。这个不是被默认应用到所有的视图,通过/Views/_ViewStart.cshtml文件。 如果不想让默认布局应用到视图,可以更改_ViewStart.cshtml的设置,指定另一个布局。
1 @{
2 Layout ="~/Views/Shared/MyLayout.cshtml";
3 }
4 5 @{
6 Layout =null;
7 }
2 调试MVC应用 我们会展示如何设置调试,创建断点,在程序和单元测试中运行调试。 2.1 创建项目 创建新项目,使用Internet应用模板,选中创建单元测试。在编译模式中选择调试模式。调试的快捷方式是F5。如果选择修改Web.config文件,编译选项会更新Web.config文件中的debug属性的值为true。
1 <system.web>2 <compilation debug="true" targetFramework="4.0">3 ...
4 </compilation>
不要在没有禁用debug设置的情况下,部署程序到生产环境。 2.2 调试 一个未处理的异常会导致调试中断。通过使用try..catch块,可以使一个异常变为处理过的。异常处理是非常有用的编码工具。它用来代表一个方案:一个方法无法完成它的任务,需要通知他的调用者。未处理的异常很坏,它代表一个我们意料之外没有处理的条件。 2.3 使用Edit和Continue VS调试特性中最有意思的一个是编辑和继续。当调试器终端,你可以编辑你的代码,然后继续调试。VS重编译你的程序,重建程序在调试器终端这一刻的状态。 2.4 启用编辑和继续 我们需要在两个地方启用编辑和继续
2.4.1 编辑并继续 当弹出异常后,在exception helper窗口上点击Enable editing link,改变代码,从调试菜单中选择Continue。 在这时,VS重编译我们的程序,使得我们的改变被包含在构建进程,重新启动执行,重新创建导致异常的状态,然后保持正常。浏览器收到结果的渲染。 没有编辑并继续,我们要停止程序,改变代码,编译横须,重启调试。然后使用浏览器重复导致调试终端的步骤。这是避免这最重要的最后一步。复杂的漏洞可能需要很多步骤,这样可以节省程序员的事件和头脑清醒。 3 项目范围的依赖性注入 在下面的章节,我们会看到多少不同的方式,MVC框架为你的扩展提供支持,自定义如何被请求服务。这些都被定义为接口的实现,或一个基类的派生。 我们已经见过自定义MVC框架的例子。我们创建DefaultControllerFactory类的派生类NinjectControllerFactory,为了能够使用Ninject创建controller,来管理DI。我们最终能够在程序中使用DI,但是比我们理想的,多了一些代码复制和Ninject kernels。 当MVC框架需要创建一个类的实例,它会调用System.Web.Mvc.DependencyResolver类的静态方法。我们可以添加DI贯穿一个MVC程序,通过实现IDependencyResolver接口,并通过DependencyResolver注册偶们的实现。通过这种方式,无论何时框架需要创建一个类的实例,它都会调用我们的类,我们可以调用Ninject来创建这个对象。 我们没有在SpotrsStroe中强化DI,因为我们只想要展示添加DI到控制器。下面展示如何实现IDependencyResolver接口。
1 publicclass NinjectDependencyResolver : IDependencyResolver
2 {
3 private IKernel kernel;
4 5 public NinjectDependencyResolver()
6 {
7 kernel =new StandardKernel();
8 AddBindings();
9 }
10 11 12 #region IDependencyResolver 成员13 14 publicobject GetService(Type serviceType)
15 {
16 return kernel.TryGet(serviceType);
17 }
18 19 public IEnumerable<object> GetServices(Type serviceType)
20 {
21 return kernel.GetAll(serviceType);
22 }
23 24 #endregion25 26 public IBindingToSyntax<T> Bind<T>()
27 {
28 return kernel.Bind<T>();
29 }
30 31 public IKernel Kernel
32 {
33 get { return kernel; }
34 }
35 36 privatevoid AddBindings()
37 {
38 Bind<IProductRepository>().To<EFProductRepository>();
39 Bind<IAuthProvider>().To<FormsAuthProvider>();
40 41 EmailSettings emailsSettings =new EmailSettings
42 {
43 WriteAsFile =bool.Parse(ConfigurationManager.AppSettings["Email.WriteAsFile"] ??"false")
44 };
45 46 Bind<IOrderProcessor>().To<EmailOrderProcessor>().WithConstructorArgument("settings", emailsSettings);
47 }
48 }
这个类很简单。前两个方法是当MVC框架需要类的一个新实例时被调用,我们简单地调用Ninject kernel传递给请求。我们添加了Bind方法,所以可以从类外面添加绑定。这完全是可选的,因为我们也包含AddBindings方法,从构造器中被调用。 现在可以删除NinjectControllerFactory类,并在Global.asax中的Application_Start方法注册更一般的NinjectDependencyResolver类。
1 DependencyResolver.SetResolver(new NinjectDependencyResolver());
通过这些设置,我们将Ninject放到了MVC程序的心脏。偶们可以继续改进MVC框架的这个扩展点,但我们不在需要,因为我们想做的知识介绍DI到请求管道的一些部分。 |
请发表评论