📜 ⬆️ ⬇️

Preparing ASP.NET5, issue number 2 - repeat the basics for the most beginners

Friends, before you the second edition of the column about ASP, NET5, in which we get acquainted with various interesting things from the world of web development on the new version of the open platform ASP.NET5.


Last time we talked about new approaches in working with static content on the platform. In the comments there was a suggestion to talk in the next issues about the basics for web developers who are just starting to use ASP.NET and dive into the topic. We listened to you and offer in this issue material from Andrey Veselov ( StealthDogg ) - a web development expert, author of many articles on ASP.NET and Microsoft MVP.

Meet the introduction to the basics of ASP.NET5 - controllers, views and models.
Note. This article is relevant for the final version of Visual Studio 2015 with ASP.NET5 Beta5. To upgrade to new versions of ASP.NET, use the release notes.

Work with controllers


Let's look at the work of the controller and the actions of the MVC template on the example of a small web application.
aspnetcolumngithub Tip! You can try everything yourself or by downloading the source code from GitHub https://github.com/vyunev/AspColumnControllerDemo .

Create a project


To do this, create a project ControllerDemo (Fig. 1).
')

Figure 1 - Creating a project web application ASP, NET5

In the project settings, select the Empty template from the ASP.NET 5 Templates section (Fig. 2).


Fig.2 - Choosing a web application template

After creating the project, the following elements will be displayed in Solution Explorer (Fig. 3).


Fig.3. - Template structure

Now you need to connect ASP.NET MVC 6 to the project.

1. In the project.json file, we specify the dependency on the Microsoft.AspNet.Mvc library.

"dependencies": { "Microsoft.AspNet.Server.IIS": "1.0.0-beta5", "Microsoft.AspNet.Server.WebListener": "1.0.0-beta5", "Microsoft.AspNet.Mvc": "6.0.0-beta5" }, 

2. Then you need to enable ASP.NET MVC 6 in the Owin pipeline to process requests and configure routing. To do this, in the Startup.cs file, add the following lines:

 public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } public void Configure(IApplicationBuilder app) { app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }); }); } } 

The project has been prepared and you can start creating controllers and actions.

Controllers and actions


As a rule, controllers are placed in a special folder Controllers. ASP.NET MVC 6 allows you to use other folders as well. looking for them in the base class. However, in this example we will focus on the classic version of the location of files. Using the context menu, create a folder Controllers ("Add> New Folder") and in it a new class HomeController ("Add> New item ..." and select Class).

Note. The name of the controller class always consists of the name of the controller (in this case, “Home”) and the end of “Controller”.
Council In the future, to create controllers, you can use the template MVC Controller Class. But now, in order to study, we will create an ordinary empty class.

The base class for all web application controllers is Controller. Therefore, we will inherit the created class from it:

 public class HomeController : Controller { } 

The Controller class is not only a marker of controllers, but provides the main functionality for working with the received request and forming a response. At the moment, its properties such as:


In addition, it provides a number of useful methods that will be discussed a little later.

For the immediate processing of the request in the controller is responsible for the action, which can be divided into the following parts:

  1. Specifying a specific type of request using the attributes [HttpGet], [HttpPut], [HttpPost], [HttpPatch], [HttpDelete]. You can also specify several types using [HttpMethod]. In this case, requests of other types will be ignored. If there are no attributes, then the action will be invoked for any request.
  2. The result of the action - its type is an implementation of an IActionResult. All actions must return an instance of the class that implements the specified interface. In essence, he is responsible for forming the response that will be sent to the client. This can be an HTML page, file, redirect or error code.
    The base Controller class contains methods that are appropriate in most standard cases:

    1. View () - creating a response (html-pages) using the view;
    2. Content () - is designed to pass an arbitrary text string to the client, for example, it can be generated by CSS or JavaScript;
    3. File () - allows you to return the file to the client;
    4. Json () - converts an object to JSON format and returns it to the client;
    5. Redirect (), RedirectPermanent (), RedirectToAction (), RedirectToRoute () - redirect the client to a new address.

  3. The name of the action for which he will be called. By default, the query string is considered to conform to the format: www.site.com/<Controller> / <Action>
  4. The action method may have parameters. Values ​​for them ASP.NET MVC will try to take from the query string. The comparison of the parameters of action and request is carried out by name.
  5. Finally, the body of the method in which the necessary data is prepared and the result is returned.

It is time to add the first action - Index:

 public class HomeController : Controller { // GET: /Home/ public IActionResult Index() { return this.Content("Hello ASP.NET MVC 6."); } } 

If you now run a web application, then the specified string is "Hello ASP.NET MVC 6." will be displayed in the browser.

Let's see what exactly happened:


If the requested controller or action is not found, the response will be sent "404. Page not found".

Let's slightly complicate and create a class constructor and one more action:

  public class HomeController : Controller { private readonly string _time; public HomeController() { this._time = DateTime.Now.ToString("G"); } // GET: /Home/ public IActionResult Index() { return this.Content("Hello ASP.NET MVC 6"); } // GET: /Home/Echo/ public IActionResult Echo(string message) { return this.Content($"{this._time} > {message}"); } } 

Now, the creation time of the controller and the string passed in the request will be returned as the response. This will ensure that a new instance of HomeController is created with each request.

To call the created action, you need to refer to the path that includes the names of the controller and the action itself. Launch the web application and enter the following address in the browser:

http: // localhost: [port] / Home / Echo? message = Hello

Asynchrony is just


Consider how easy ASP.NET MVC 6 allows you to create asynchronous methods. Redo the action Echo. To simulate a call to a certain asynchronous method, we use Task.Delay ():

 public async Task<IActionResult> Echo(string message) { await Task.Delay(100); return this.Content($"{this._time} > {message}"); } 

It only took to replace the result type from IActionResult with Task <IActionResult> and add the async modifier. Such an action can use calls to asynchronous methods, for example, to access various data sources or services.

Some practice


And finally, two small practical tasks:

  1. Write an action that also displays the value of the parameters, but which are sent to the request of type POST only.
    Hint. To form a request, you can use a regular HTML page with a form. Place its file in the already existing wwwroot folder, which is intended for any static site content (html pages, files, etc.)
  2. Create an action that responds only to the Get request and:
    • returns a file;
    • returns an object in Json format (for simplicity, you can use an anonymous class);
    • redirects to another page.

And do not rush to look into the attached source code, where there are all the solutions. Try to do it yourself.

Work with views


Let us turn to the consideration of the next component of the MVC pattern - views.
aspnetcolumngithub Tip! You can try everything yourself or by downloading the source code from GitHub https://github.com/vyunev/AspColumnViewDemo .

Create a web application with a view


To do this, create an empty ASP.NET MVC web application, ViewDemo, in the same way as was done in the previous section. Only this time, the HomeController controller will look like this:

  public class HomeController : Controller { // GET: /Home/ public IActionResult Index() { return this.View(); } } 

The View () method creates the result of an action using a view. Let's try to start the project and immediately get an error message, because The project does not yet have a representation for the Index action (Fig. 4).


Fig.4 - Error message when the view is missing

If you carefully read the message text, you can see that there is a clearly defined place for the submissions in the project structure. This is the Views folder. It contains subfolders with names corresponding to the names of the controllers. In this example, it will be Home. And it already stores view files, the file names of which, in general, coincide with the names of the actions for which they are intended.

In addition, there is a special folder Views / Shared. It contains views available for any actions in the project.

Create the above Views and Home folders. After that, in the latter, using the context menu "Add> New Item ...", add a view (MVC View Page) with the name Index.cshtml. The cshtml extension indicates that the Razor markup language will be used. As a result, the project will look as follows (Fig. 5):


Fig.5 - Project structure with a new view

Add the following code to Index.cshtml:

 <h1>View Demo</h1> 

Run the web application. When this happens the following:

  1. The Index action of the Home controller will be triggered (as described in the previous article).
  2. In the Index action, the View () method will use the View / Home / Index.cshtml view to create a result (an instance of a class that implements an IActionResult).
  3. The result of the action will generate the HTML code in response to the client (in the ExecuteResultAsync method of the IActionResult interface).
  4. The created page will be sent to the client and displayed by its browser.

The View () method looks for a view using the following paths:

  1. First View / <Controller Name> / <Action Name> .cshtml
  2. Then View / Shared / <action name> .cshtml

If both searches have brought nothing, then an error message is displayed.

There is a method overload that allows you to explicitly specify the name of the view. For example, call

this.View ("MyView") will look for the View / <Controller Name> /MyView.cshtml or View / Shared / MyView.cshtml file. This can be useful, for example, if an action should produce a different result depending on some condition.

In addition, there is a variant View (), which allows to transfer data to the view. This will be discussed in more detail below. And now a little analyze the possibilities of Razor.

Razor Markup Language


Basic designs

Razor allows the following constructions:


In them, C # code can be combined with HTML code, for example:

 @for(int i=0; i<10;i++) { <p>@i</p> } 

It should be noted that the presentation is essentially a class that implements the IRazorPage, with its properties and methods. For example, the ViewBag and ViewData are available, which contain the values ​​in which they were added in the action.

There is also an Html property that provides a large number of helper methods. Here are some of them:


Another auxiliary property is Url. It contains methods for working with paths in a web application. Probably the most popular of them is @ Url.Action (...), which displays the path to the specified action of the specified controller, for example: <a href="@ Url.Action("Index", "Home”) a>.

It is also necessary to note the special Views / _ViewStart.cshtml file. Its presence is not necessary, but if it is present in the project, its content is performed before each presentation. With it, you can set a common page template for all views.

Page Templates


As a rule, a web application contains dozens of pages. Practically each of them will have its own presentation, and therefore its own file with HTML code. However, many pages have the same template and differ only in part with the main content (content).

In order not to insert a copy of the HTML code of the page into each file of the presentation, you can use the layout. For this you need:

  1. Create a shared markup file in View / Shared
  2. In _ViewStart.cshtml or the action itself, the markup file is specified using the Layout property.
    Hint: If the template is specified both in the file and in the view, the one specified in the view will be used. Thus, you can set a default template in _ViewStart.cshtml, and, if necessary, override it in the view.
  3. The place where the view code will be inserted into the template is marked with a call to @RenderBody ().

So, in the View / Shared folder, create a file with the HTML markup template _Layout.cshtml (the name can be arbitrary):

 <html> <head> <meta charset="utf-8" /> <title>@this.ViewBag.Title</title> </head> <body> <nav>Menu</nav> <section id="mainContent"> @RenderBody() </section> <footer>Footer</footer> </body> </html> 

Let's also change the presentation code:

 @{ this.ViewBag.Title = "Home page"; this.Layout = "~/Views/Shared/_Layout.cshtml"; } <h1>View Demo</h1> 

As you can see, this code:

Now when you start the web application, the page will be displayed using the specified template. The string "Home page" will be inserted into its title.

Sections


It is possible to insert code from a view into a page template outside the block code created by @RenderBody (). These are sections that work as follows:

  1. The template code indicates where to insert sections using @RenderSection (name, required) or @RenderSectionAsync (name, isRequired). Where name defines the unique name of the section, and required defines whether it is mandatory.
  2. Views define the content for sections using the @section name {...} construct
  3. In the absence of code for the mandatory section, an error message will be displayed.

It should be noted that sections can be located not only in the body of the page, but also in its title. For example, this can be used to connect external JavaScript libraries required only on individual pages.

Let's move on to an example. Define an optional section in the page template

 <html> <head> <meta charset="utf-8" /> <title>@this.ViewBag.Title</title> </head> <body> <nav>Menu</nav> <section id="mainContent"> @RenderBody() </section> <footer>Footer</footer> @RenderSection("scripts", required: false) </body> </html> 

Now we will set the code for this section in the view. For clarity, call alert ():

 @{ this.ViewBag.Title = "Home page"; } <h1>View Demo</h1> @section scripts { <script> alert("Demo"); </script> } 

Run the project and make sure the JavaScript has been added to the page and executed.

Partial views


Another convenient feature of Razor is the creation of partial views. This can be used to store duplicate page elements (pop-up dialogs, forms, etc.), and to logically split a large page into parts.

Using partial views is very simple:

  1. Create a partial view as normal
  2. Specify Layout = null in it to stop using the page template.
  3. To insert a partial view use Html .Partial () or Html .PartialAsync ().

As always, let's move on to the example. In the new Views / Shared / Forms folder, create a partial view_ContactForm.cshtml file with the following contents:

 <form> Message: <input type="text" /><button type="submit">Send</button> </form> 

We derive it in the Index view:

 @{ this.ViewBag.Title = "Home page"; } <h1>View Demo</h1> @Html.Partial("Forms/_ContactForm") @section scripts { <script> alert("Demo"); </script> } 

Notice how the path to the partial view is given. His search follows common rules, and in this case the path is specified relative to Shared. The file with it can be placed in any folder inside the View, and at the same time it will have to specify in the method parameter the full path relative to the site root. For example, Html .Partial ("~ / Views / Shared / Forms / _ContactForm")

It remains only to start the project and make sure of the result.

View Components


Speaking about representations, it is necessary to cancel such innovation of ASP.NET MVC 6 as components. In essence, this is the development of the idea of ​​partial representations by adding own controllers to them. However, you must first understand the use of models. And then it will be possible to return to the components in the following sections.

We work with models


Applications created in the previous parts already contain a controller and a view. It remains to consider how to use another component of the MVC pattern - the model.
aspnetcolumngithub Tip! You can try everything yourself or by downloading the source code from GitHub https://github.com/vyunev/AspColumnModelView .

Create a model


We use the ViewDemo application created in the last part and add to it the work with the model.

To place the models in the project, create the Models folder. This name is recommended, but not mandatory. Their code can be placed in folders with other names. In addition, you can use subfolders for logical grouping of classes.

A model is a simple object (POCO). There is no need to inherit it from any class or implement any interface. Create a model that, for example, will contain the user name and the current time. To do this, add the IndexPageModel.cs file to the Models folder with the following code:

 using System; namespace ViewDemo.Models { public class IndexPageModel { public string FirstName { get; set; } public string LastName { get; set; } public string FullName => $"{this.FirstName} {this.LastName}"; public DateTime CurrentTime { get; set; } } } 

The model is ready. Please note that there are no restrictions on the model class. For example, in this case, the computed property FullName is present. However, you should not get carried away and transfer the logic of the application in the model. It is better to keep them as simple as possible in order to facilitate further maintenance of the application.

Modifying the controller


So, the model is already there. It is necessary to create its copy and to write down in it any values. For simplicity, we use constants. Let's go to the Home controller and modify the Index action as follows:

 public IActionResult Index() { var model = new IndexPageModel() { FirstName = "John", LastName = "Doe", CurrentTime = DateTime.Now }; return View(model); } 

To transfer a model to a view, it is enough to substitute its instance as a parameter of the View () method. In this example, constants are used to populate the model. Of course, in a real project there will be an appeal to the business logic of the application and the result will be substituted into the model.

Modifying the view


Open the Index.cshtml view. First you need to specify that it will use a certain class of model. To do this, in the first line of the file write the following:

@model ViewDemo.Models.IndexPageModel

Note that the class name is specified along with its namespace.

Now you can use the this.Model property, which will contain the transferred model of the specified type. We will display the data on the page (the full code for the Index.cshtml view):

 @model ViewDemo.Models.IndexPageModel @{ this.ViewBag.Title = "Home page"; } <h1>Model Demo</h1> <p><strong>  :</strong> @this.Model.FullName</p> <p><strong>   :</strong> @this.Model.CurrentTime.ToString()</p> 

Run the application. Each time the page is refreshed, the name, surname, as well as the current date and time specified in the controller will be displayed.

So, creating and using models is no more difficult than regular classes. ASP.NET MVC takes all the work of transferring its instance to the view. In addition, in the view, the this.Model property becomes the same type as the model. IntelliSense .

Latest news


As you already know, Visual Studio 2015 is released with ASP.NET5 Beta5. Details about what exactly is included in the release of Visual Studio can be found in this blog .

Released ASP.NET5 Beta6 update with many changes, improvements, and bug fixes. Details of the update can be found in this blog . You can download the update from this link .

Plans have been published for the release of platform releases in the coming months before the release of the final version of ASP.NET5. According to them, we are waiting for versions Beta7 and Beta8, after which in November we will receive the first version, ready for production (RC1), the final version will be released in the first quarter of 2016. Details of each version can be found on the link .

Published reports of the DevCon 2015 conference, including on web development and the topic of ASP.NET .

useful links


The latest ASP.NET5 documentation is located at http://docs.asp.net/en/latest/ .

We invite you to connect to the live broadcasts of the periodic show ASP.NET 5 Community Standup , where developers from the Microsoft team share the latest news about the platform. Entries are available at this link .

Check out the new article on the development of ASP.NET applications in Visual Studio Code by Eric Reitan, which details the interesting aspects of working with web projects in VS Code.

Learn the basics of ASP.NET5 with the new free course of the Microsoft Virtual Academy.

To authors


Friends, if you are interested in supporting the column with your own material, please write to me at vyunev@microsoft.com to discuss all the details. We are looking for authors who can interestingly tell about ASP.NET and other topics.

about the author



Senior Developer, CodeFirst, Ireland

15- , Microsoft MVP (ASP.Net/IIS). 9 - Microsoft. : ASP.NET Azure. CodeFirst Senior Developer. .

Twiter: twitter.com/AndreyVeselov
Facebook: www.facebook.com/veselov.andrey
: andrey.moveax.ru

Source: https://habr.com/ru/post/264271/


All Articles