ASP.NET MVC with a real example. Theory and introduction.

    The Microsoft team is very intensively developing its products and tools for developers. There are already exhausts on this subject.there were comic ones about the release of new versions of frameworks. Developers who work in large companies are involved in large projects, in general, they do not look at it very enthusiastically, since such engines can not be quickly transferred to a new version. It can be fraught with both pop-up bugs and a change in the entire structure of the project, which is not always easy to do. The above, unfortunately (or fortunately), does not concern me, and this gives me the opportunity to use the latest without looking at the background. The projects are pretty visible, they are often transferred to the new version painlessly, and I begin to introduce new features when implementing the next task in the project. At the time of implementation, this, of course, introduces some kind of chaos in the code, as different principles are used in different pieces of code (for example, LINQ implementation),

    Why all this?


    One of these innovations is ASP.NET MVC , an implementation of the Model-View-Controller template for the .NET platform. Let's try to figure out what it is, why it is needed, and apply our knowledge on a simple but real application.


    How MVC works


    The architectural pattern of Model-View-Controller implies dividing the application into three main components: Model, View and Controller, is it strange? :) Each of these components is responsible for its tasks. If in general terms, then:
    • Model is basically the whole business logic of our application. It contains classes that are responsible for our data (entities), manipulate them, write to the database and read from there, as well as for the interaction between the entities themselves. If our application is small, then most likely we are right here and will work with data. If the project is larger, contains a lot of logic, then it is better to take out the logic and work with data in separate projects (assemblies). And when we encounter a very large application, we will have to physically transfer it to other servers (Application Server).
    • View is responsible for user interaction (UI). Through it, we will display our data to the client, implement an interface for editing them, and much more. But only what is associated with the display. No logic!
    • Controller is our link between the first two components. Controller Receives data about our request to the server, somehow processes this data (for example, receives values ​​from the submitted form) and passes them to Model. After processing or receiving data, he chooses the exact way we display the data to the client (the desired View).


    What does this give us useful? We get full control over the HTML output. Lighter applications. Adherents of TDD (Test-Driven Development)will be delighted, MVC allows this approach to be used to its fullest and test almost everything. We also get a complete separation of logic from the presentation of data. Someone simply says, “finally, everything is for people”, and someone will discipline it so that they don’t write a code for working with data in the handler clicking a button. By the way, did I mention handlers? Forget it. This is no more. No event handlers, no ViewState, no Drag'n'Drop controls per form. Yes, you’ll have to hardcode more with your hands, someone can even learn and find out how it all really works. At the same time, if we lost features that simply contradict the idea of ​​MVC, we did not lose the main one. At our disposal were MasterPages, UserControls, Membership. In general, everything is not so bad as it might seem at first glance. Is MVC replacing WebForms? No, WebForms will also live and evolve. MVC just makes it possible to write applications differently. If you have an application for working with a bunch of data, editing in a GridView, etc., then WebForms will remain the right solution for you. Even with MVC, you will forget about all the problems with URL-Rewriting, maybe this is not so a problem in WebForms, of course, but for MVC it ​​is a native feature.

    From theory to practice?


    The other day I came across a project from a good friend. Need a new website for a portable electronics service center. Old is, but a little frustrating. In fact, nothing complicated: five information pages, a catalog of affordable accessories with prices and integration with 1C. For the sake of the latter, the question arose. The entire database is maintained at 1C, I want the client to be able to go to the site and enter the number of his receipt and see the status of the repair: he’s not ready, is everything repaired under the guarantee or will have to pay extra for something.

    Preparation for work


    First, you must have Microsoft Visual Studio 2008 installed (if I’m not mistaken, then the Express edition should also be suitable), .NET Framework 3.5 , and ASP.NET MVC itself (Preview 3 is available at the time of writing). After the successful installation of all the good, we will create our project. File -> New -> Project ... In the window that opens, select in Project Types the language you are writing in and the type of Web project, among the proposed templates, we need ASP.NET MVC Web Application. My project is called "ITService".

    Project creation

    Next, we will be asked to create a Unit Test Project for our application, while we get along without it.
    As a result, we got our clean project in this form:

    ASP.NET MVC Project Content

    Along with already familiar directories, unfamiliar to us appeared. Let's go in order:
    / Properties - the standard directory for Web Application, contains the project settings.
    / References - links to other assemblies, projects, etc.
    / App_Data - a special directory for storing data
    / Content - in this directory we will store images, styles and the like. In general, all the static content of the site
    / Controllers - the classes responsible for the components of the Controller
    / Models - the classes with our logic
    / Views- directly the UI of our application. In this directory, directories are created for each controller (/ Views / Home in our case). And they already have an aspx page for each of the methods of the controller.
    / View / Shared - contains what can be useful for all controllers, for example MasterPages and UserControls.

    Well, try to run? Voila! Got the result:

    The first launch of the application

    Click on the links in the top menu and see how the URLs are organized in MVC by default. The About page has the localhost address : 55515 / Home / About (your port may vary). It turns out we have such a structure mysite {controller} / {action}. Well, that's pretty good.

    What we need


    As I said, I need a site with several information pages, a catalog of accessories and a special page that will receive and output data from 1C. OK, first we’ll try to implement our static pages, lay out MasterPage, write the styles we need and get them to work. Of course, in a more complex application, you should start by developing business logic, think about how we will store the data, write all this, and only then proceed to the interface. But in our case, the project is small, so this sequence can be neglected.

    Making life easier when writing code


    If you look at our Site.master, we will see that the path to css, for example, is relative there, i.e. ../../Content/Site.css. This does not suit us, since the nesting of our pages will be different, and the link will be lost, you need to fix it on the path from the root. For CSS, it would be possible to register with pens, of course, but looking ahead I’ll say that we also have pictures on the site. Each time it’s boring to write to them quite a long way, therefore, we will make Helper. Create the Helpers folder, add the AppHelper class to it with the following code:

    using System.Web;

    public static class AppHelper
    {
      public static string ContentRoot
      {
        get
        {
          string contentVirtualRoot = "~ / Content";
          return VirtualPathUtility.ToAbsolute (contentVirtualRoot);
        }
      }

      public static string ImageRoot
      {
        get {return string.Format ("{0} / {1}", ContentRoot, "Images"); }
      }

      public static string CssRoot
      {
        get {return string.Format ("{0} / {1}", ContentRoot, "Css"); }
      }
      
      public static string ImageUrl (string imageFile)
      {
        string result = string.Format ("{0} / {1}", ImageRoot, imageFile);
        return result;
      }

      public static string CssUrl (string cssFile)
      {
        string result = string.Format ("{0} / {1}", CssRoot, cssFile);
        return result;
      }
    }


    In it, we declared the static property ContentRoot - the path to our content, the path to the directories with images and css files, as well as 2 static methods, ImageUrl and CssUrl, which take the file name and return the corresponding path to it in our application. In order to use our class, we will change the link tag connecting styles in Site.Master to the following:

    "rel =" stylesheet "type =" text / css "/>


    And do not forget to move Site.css to the created directory / Content / Css, we will separate the static content by its type. Now if we recompile our project, the path will be written correctly:



    At this stage, we wrote our Helper to prescribe the correct path to images and style sheets. Next, we’ll look at how we can work with HTML in general and what we are offered.

    HTML work


    Microsoft offers HtmlHelper to facilitate code writing. This is a class with a set of static methods that allows you to render the necessary HTML tags. For example, to display a picture, just write

    <% = Html.Image ("image.png", "Alt text")%>


    On the page it will look like



    If we use our AppHelper to calculate the path to the picture, we will write like this:

    <% = Html.Image (AppHelper.ImageUrl ("logo.png"), "Alt text")%>


    This code will already generate the correct picture and write the desired path:



    Another interesting method is Html.ActionLink:

    <% = Html.ActionLink ("About Us", "About", "Home")%>


    This method will generate a link to the “About” method of the “Nome” controller with the text “About Us”.
    You can write the same code using the Lambda Expressions using more “modern” methods:

    <% = Html.ActionLink(x => x.About (), "About Us")%>


    What is going on here, I think, is clear from the syntax.

    A small hint: in order not to write the ITService.Controllers namespace each time, we will write it in web.config in the section :

    Now, these links can be written shorter:
    <% = Html.ActionLink(x => x.About (), "About Us")%>



    Separately, it is worth mentioning the form. We will now have to work with them explicitly enough (no Postback, remember?). The simplest form would look like this:

    <% using (Html.Form(x => x.Index ())) {%>
    <% = Html.TextBox ("name")%>
      <% = Html.SubmitButton ("cmdSend", "Send")%>
    <%}%>


    To work with the from tag, we need to use the using directive and register all form fields in its scope. This will provide us with a closing tag. The Html.Form declaration (x => x.Index ()) also indicates that the form will be submitted to the Index method of the HomeController. I think that they came up pretty well. At first, when I saw this mixture of html and server parts of the code, I was horrified, I think everyone came. Hello again, classic ASP, where this vermicelli was full. But still not so scary. This is not at all what it seems at first glance when you start working with him. All of these tools are really powerful.

    ASP.NET Routing


    What are routers? Routers allow us to work with URLs that do not point to physical files on our server; instead, the path is sorted into parameters that we already use in our application. We can also map a certain part of the path to a specific controller and its method. Such a model is used by default, but we can set correspondences that are convenient for us. On the one hand, this is similar to the good old URL-Rewriting, which we already wrote about in detail on the hub in the article, but this is only on the one hand. These are actually two different things. If we use UrlRewriting, then a query of the form mysite.com/products/product1 is converted when executed to mysite.com/products.aspx?id=product1. Natively, we cannot generate URLs that comply with our URL rewriting rules. Therefore, if we change the logic somewhere and change the address patterns, we will have to edit all the places where these URLs are generated with pens. In MVC, no transformations occur, since it itself parses the path that is passed to it without problems.

    All work with Routers in MVC is organized in Global.asax.cs. Let's look there in our project and see the following:

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


    As you can see, we are adding our own to the collection of routers with which our application operates. With the name Default, we prescribe the URL mask and create an anonymous type in which we prescribe the default parameters. We will make changes here when we go directly to the implementation. At the same time, if you are satisfied with such an address generation scheme, then why not? You can leave it as it is and it will work too.

    End of beginning


    Well, this was the introduction, in which I tried to reveal the most basic concepts about the ASP.NET MVC platform. It is up to you to judge how much I did. I myself am not an expert in this field, it just became interesting for myself, but at the same time I decided to share it with people, as there is very little information in RuNet on this topic.

    I want to note that your opinion about everything is important to me, so any feedback will be by the way. If there is criticism, then of course I am sure that it will be constructive;)

    In the following articles I will go directly to the implementation of the conceived application. Most likely there will be more code. And it doesn’t please me with such formatting as on the Habré :)

    * All the code in the article was highlighted, as far as it was possible, using Source Code Highlighter .

    Also popular now: