Programmer's architectural design path (8): MVC

Source: Internet
Author: User
It is hard to understand that when WebForm appears, the program will be excited in the world. In fact, I switched to MVC only after Razor appeared.

WebForm

With the rise of ASP. net mvc, WebForm has become yellow yesterday, but I still want to say a few words for WebForm.

It is hard to understand that when WebForm appears, the program will be excited in the world. In fact, I switched to MVC only after Razor appeared, because I was afraid of seeing <%>. I have participated in a project to upgrade ASP to ASP. NET. the messy code in ASP makes my eyes sour and swollen, so I can remember it all my life!

The final html generated by WebForm may be bloated and ugly, but its code page (. aspx) is quite refreshing and beautiful.

Since we have all decided to adopt MVC, we don't need to talk about the shortcomings of WebForm. However, we should study hard and learn from its excellent advantages. these are also used in MVC development:

• The rendering and page logic are separated. In WebForm, because its framework originally explicitly distinguishes aspx and aspx. cs, we will not worry about this most of the time. But in MVC, we can easily use ViewModel data in the view to perform operations and blur the logical boundaries between the Controller and the View. We will explain this problem in detail during CurrentUser.

• Good page encapsulation and reuse. When we find that the pages are repeated and similar "parts", we will surely think of reuse. This is the time to test our skill. I would like to mention one thing I think of first: sometimes we would rather repeat them than reuse them! This is my tears. It should be in the comments page of the home project of entrepreneurship. I tried to reuse all comments in PartialView. The results were terrible, and I finally gave up reuse, but it was a sea of sky. In fact, a better example is the GridView and Repeater in WebForm. In practice, the Repeater in simple encapsulation is more popular, while the "big and complete" GridView is rarely used. Therefore, encapsulation and reuse have a problem.

RouteTest

The Route function is a major breakthrough of MVC and an important defect. Because there is no good automatic check mechanism, it is very error-prone in the actual development process! I believe that all those who have experience in development have some experiences. sometimes, when I get an error for a long time: no View can be found, no Action can be found, and a spelling error can be found. sometimes a RouteConfig is added, after a while, other colleagues shouted, "test! It turns out that your settings overwrite my settings. I checked it all afternoon !"

It is a pity to waste time in these places, so our solution to this problem is to use unit testing and introduce RouteTest in the PCTest project. Each time you add RouteConfig and run the unit test: if you can pass the test without affecting others, you will be OK.

This is the most successful example of unit testing at the UI layer of our project. The biggest benefit of MVC is that it can be tested. unit tests should be widely introduced elsewhere, but I am lazy, in addition, the sealed limitation of HttpContext also limits the implementation of unit testing (MVC 5 should solve this problem). Therefore, the unit testing at the UI layer has not yet been expanded. However, it is estimated that this work will have to be done sooner or later. now there are some problems that are complicated and easy to miss in manual testing.

URL/View level

Another problem with MVC is that it is difficult for a View to be organized by multiple layers. For example, the View I may need is organized as follows:

Note that the Controller also has hierarchical relationship settings. I always think this will be clearer and more clean, but if the MVC framework cannot be "hierarchical ". If the View must be organized in layers like this, all the paths of the View must be written in the Action, for example:

C # code
  1. Public class LogController: Controller
  2. {
  3. //
  4. // GET:/Account/Log/On
  5. Public ActionResult On ()
  6. {
  7. Return View ("~ /Views/Account/Log/On. cshtml ");
  8. }
  9. }

It is too troublesome to configure RouteConfig. Therefore, we should try our best to follow the MVC framework. starting from the URL design, we should try to adopt the/{Controller}/{action}/{route-parameter} style, view is also placed in the corresponding folder of Contoller.

Partial/ChildAction/EditorTemplate

When we need to reuse some "page fragments", we are faced with the above options. There are a lot of cutting-in points. we only use our projects to extract the most distinctive and easily identifiable features and directly describe their use scenarios:

The first is EditorTemplate. It has the most obvious characteristics and is related to Post. That is, when the data of a "page segment" needs to be Post back to the server, we must use EditorTemplate. if EditorTemplate is not used, ViewModel data cannot be returned. Why? It is related to the ViewModel binding mechanism of MVC. when the html control in EditorTemplate is rendered, the prefix of the parent Model is added to its name, so that MVC can automatically parse post data and bind it to the ViewModel.

If "page fragment" does not require POST, it is only responsible for rendering. what should I do? Our principle is:

• If the "page fragment" does not need to interact with the server, all required data can be obtained from the parent Model and Partial is used;

• Otherwise, if the "page fragment" says the required data still needs to be obtained from the server, ChildAction is the only option.

HtmlHelper

In addition to the reuse of the preceding page fragments, you can also customize a "page fragment" rendering method by creating HtmlHelper extension methods. This method is generally an alternative to PartialView. we usually take "very small" (such as a link or a drop-down list) for "a lot of use" (or even cross-project) html snippets can be encapsulated with HtmlHelper.

AJAX

By observing our actions, we can find that the Action we provide for Ajax is always the returned ActionResult, rather than the "more advanced" WebApi mechanism (directly returning simple types such as int ). This is mainly because we use the SessionPerRequest mechanism (mainly to improve performance). we make a Request use only one session (which can be simply understood as a database connection), that is:

1. when MVC obtains a Request and requires a session, the Service generates a session;

2. then, the generated session will be used throughout the Request process (similar to the "Singleton mode ");

3. when the Request ends, release the session and synchronize all changes to the database.

Okay. The key point here is when the Request is "ended "? We further define it as when the View is rendered, so we use the Filter mechanism to synchronize the database during OnResultExecuted (). The code is as follows: So even if Ajax calls, you must also go through a "View rendering completed" process to complete data synchronization.

UIDevService switchover

For foreground development, you do not need to connect to the background database. you only need to enter UIDEV when compiling the MVC project (if you want to actually connect to the database, use PROD), as shown below:

So how is this actually implemented?

In general, we borrowed the autofac class library to implement the so-called "Dependency Inversion"

Therefore, in the MVC Controller, we only use ServiceInterface, regardless of its specific implementation, as shown below:

C # code
  1. Private IAuthroizationService _ authService;
  2. Public AuthController (IAuthroizationService authService)
  3. {
  4. _ AuthService = authService;
  5. }

Finally, in Global. asax. cs, we use the condition compiler if... else to determine which Service implementation is used: ProdServiceModule or UIDevServicemodule.

C # code
  1. Void ResolveDependency ()
  2. {
  3. Var builder = new ContainerBuilder ();
  4. Builder. RegisterControllers (Assembly. GetExecutingAssembly ());
  5. Builder. RegisterFilterProvider ();
  6. # If PROD
  7. Builder. RegisterModule (new ProdServiceModule ());
  8. # Endif
  9. # If UIDEV
  10. Builder. RegisterModule (new UIDevServicemodule ());
  11. # Endif
  12. Container = builder. Build ();
  13. DependencyResolver. SetResolver (new AutofacDependencyResolver (container ));
  14. }

Finally, do not forget to add the following to ProdServiceModule. cs or UIDevServicemodule. cs when a new Service is introduced:

C # code
  1. Builder. RegisterType (). ();

This chapter is almost the same. In the next chapter, we will talk about CurrentUser and introduce our principle: how to divide logic (or responsibility) between View, Controller, Service, and ViewModel ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.