CHAPTER 5
HTTP isn’t just for serving up webpages; it’s also for serving APIs that expose services and data over HTTP protocol. This chapter will gently introduce you to managing these scenarios using ASP.NET MVC, which hasn't changed much from the previous version.
You’ll manage controllers, views, APIs, the newest and coolest tag helper, and you’ll play with the view components. But before proceeding, it’s important to know that the part related to MVC is just a small introduction. A complex framework like it would easily require an entire book, which is not the scope of a work targeting ASP.NET, such as this book.
Web API (application programming interface) is a set of subroutine definitions with the scope of managing data between clients and servers. Over the last few years, the trend has been to build APIs over HTTP protocol, allowing third-party apps to interact with a server thanks to the application protocol.
Probably the most well-known example is Facebook, which allows users to share content, posts, manage pages, and do more from any client—mobile app, desktop, or whatever. This is due to a set of APIs and HTTP, but how does it work?
The good thing about using HTTP protocol is that there are no major differences between the classic web navigation except for the result. In a normal HTTP navigation, when we use a browser to call www.tostring.it, the server returns HTML. For the APIs, it returns data using JSON format.
The result could also be XML or any other type of structured data. The point is that the result doesn't contain any information about the layout or interaction, like CSS and JavaScript. With the previous version of ASP.NET, a specific library managed APIs. It was called Web API.
With the newest version, this library doesn’t exist, and you can handle API and classic requests using the same framework because Web API has merged into the MVC framework. This is the primary difference between the old ASP.NET and the new.
When you think about what we were using in the previous version, it makes absolute sense.
Most of the code between the two frameworks was similar. Think about the controller, attributes, and dependency injection—same code, different namespaces.
ASP.NET MVC Core is not different from what you saw in the previous chapters; you have to install and configure the necessary packages respectively using NuGet and the Startup class.
The package is Microsoft.AspNetCore.Mvc, and it has built-in support for building Web APIs. Once you have it installed, register the service and configure it within you web application like this:
Code Listing 5-1
using Microsoft.AspNetCore.Builder; |
Because you are managing data and not HTML pages, HTTP verbs are key to understanding what the client needs. There is a kind of convention that almost all API implementations respect and use different HTTP verbs according to the type of action needed.
Suppose you have this request: api/users.
Table 1
Resource Sample | Read (GET verb) | Insert (POST verb) | Update (PUT verb) | Partially Update (PATCH Verb) | Delete (DELETE Verb) |
Action | Gets a list of users. | Creates a user. | Updates users with a batch update. | Batch-updates users only with the attributes present in the request. | Errors or deletes all users, depending on what you want. |
Response | Lists users. | New user or redirects to the URL to get the single user. | No payload; only HTTP status code. | No payload; only HTTP status code | No payload; only HTTP status code. |
In case you want to manage a single user, the request should be api/users/1 where 1 is the ID of the user.
Table 2
Resource Sample | Read (GET verb) | Insert (POST verb) | Update (PUT verb) | Partially Update (PATCH Verb) | Delete (DELETE Verb) |
Action | Gets a single user. | Returns an error because the user already exists. | Updates the specified user. | Partially updates the user only with the attributes present in the request. | Deletes the specified user. |
Response | Single user. | No payload; only HTTP status code. | Updated user or redirects to URL to get the single user. | Updated user (complete object) or redirects to URL to get the single user. | No payload; only HTTP status code. |
To summarize, the URL combined with the HTTP verb allows you to understand what has to be done.
Now that everything is correctly configured, you can create your first MVC controller. Not to deviate too much from what you used in the previous version, let's create a folder called Controllers.
Although not mandatory, the best practice is to create a folder for all the API controllers to separate API from the standard controllers.
Code Listing 5-2
using System.Linq; |
As you can see, the controller is simple and the code is not so different from the previous version. Let’s analyze this step by step.
Code Listing 5-3
[Route("api/[controller]/[action]")] |
This says that the controller can manage all the requests with the api prefix in the URL. Basically, if the URL doesn't start with /api, the controller will never handle the request.
Code Listing 5-4
[HttpGet] |
This attribute specifies the verb for the action it is decorating on. You could use all the possible verbs, HttpGet, HttpPost, HttpPut, and so on.
You just saw how to return data as well as partially read input information from the query string.
Unfortunately, this is not so useful when you have to send a lot of data from the client to the server because there is a limit related to the number of characters you can add to the URL. For this reason, you have to move to another verb.
HTTP/1.1 doesn't specify limits for the length of a query string, but limits are imposed by web browser and server software. You can find more information at http://stackoverflow.com/questions/812925/what-is-the-maximum-possible-length-of-a-query-string.
This approach is not so different from what you saw, the only difference is the place where the data comes from, the body instead of the query string.
Code Listing 5-5
// Adding user |
As you can see, the only differences are as follows.
Code Listing 5-6
[FromQuery] |
That specifies that data comes from the payload of the HTTP request.
Code Listing 5-7
return new CreatedResult($"/api/users/{user.Id}", user); |
This returns the created object and the URL where the client can get the user again. The status code is 201 (created).
Code Listing 5-8
return new EmptyResult(); |
Basically, this means Status Code 200 (OK). The response body is empty.
Code Listing 5-9
return new NotFoundResult(); |
This is the 404 message that is used when the requested client can’t be found.
In order to test the API, the browser can be used because APIs are being implemented over HTTP protocol, but there are other applications that can help with this too. One popular application is Postman, which can be downloaded for free from getpostman.com.
The following screenshots show how to test the code we used previously.
Retrieve users (/api/users using GET).

Figure 5-1: Using Postman to Test REST Endpoint-1

Figure 5-2: Using Postman to Test REST Endpoint-2
Create user (/api/users using POST).

Figure 5-3: Using Postman to Test REST Endpoint-3
Deleting user (/api/users?id=2 using DELETE).

Figure 5-4: Using Postman to Test REST Endpoint-4
As mentioned in the previous section, ASP.NET MVC isn't different than Web API, so the code you are going to see here will be very similar, except for the result.
Because you already installed and registered ASP.NET MVC for APIs, you can jump directly to the code. In the same folder (Controller) where you created UserController, you can create another controller with the scope of serving the main page of the website. In this case, call it HomeController.
Code Listing 5-10
using Microsoft.AspNetCore.Mvc; |
This code is similar to the API controller, the only differences are the missing route attribute on the controller and the View method used to return the action. The first one is not needed because you don't have to override the default routing configuration (we will discuss this later in the chapter), and the second one indicates to the controller that it has to render a view and not JSON.
If you try to run this code, you’ll get an error like this.

Figure 5-5: Unable to Find the MVC View
This happens because the MVC framework cannot find the view file, but how does it locate the file? The logic behind it is very simple, if you don't specify any information about the view, everything happens using conventions.
First, it is important to know that all the views are placed into the folder Views in the root of the project, as you can see in the following screenshot.

Figure 5-6: The Views Folder
Inside, there must be a folder for each MVC controller you created. In this case, you have just one controller called HomeController, so you must create the folder Home inside Views.
Finally, it's time to create our views. Using Visual Studio 2017 makes it really simple.

Figure 5-7: The Views Folder for the Home Controller

Figure 5-8: Adding the View-1

Figure 5-9: Adding the View-2
Now, if you open the newest file, you’ll see that it is almost empty. It contains just a few strange sections that you’ll recognize because they have different colors and use @ in the beginning.
There parts are managed server-side and contain instructions on how to change the output to render the final HTML. Everything is possible thanks to Razor, the view engine embedded with ASP.NET MVC Core.
A good introduction to Razor syntax is available at asp.net/web-pages/overview/getting-started/introducing-razor-syntax-c. Because you have to render a webpage, you first have to create the right markup, so let's add the following code to our view.
Code Listing 5-11
<!DOCTYPE html> |
When running the application again, the result should not be an error, but a simple HTML page.

Figure 5-10: Server-Side Page Rendered Using MVC
This is definitely an improvement, but you’re returning just a static file; there isn’t any kind of transformation. But that isn’t needed to use MVC because you already have a specific middleware component to manage static files.
To make the view more elaborated and to use something from the server, you have to go back to the controller and send the data to the view.
Code Listing 5-12
using Microsoft.AspNetCore.Mvc; |
Notice that we have reused the class User, which was previously created for the API response. This code doesn't need explanation; you’re just sending an array of users as a model to a View method.
In our view, it’s time to get users from the controller and print the data to the page. The first thing to do is to specify what kind of model the view is using. In our case, it’s IEnumerable<User>.
Code Listing 5-13
@model IEnumerable<Syncfusion.Asp.Net.Core.Succinctly.Mvc.Models.User> |
Now you have to iterate all the users from the model and show the data.
Code Listing 5-14
@model IEnumerable<Syncfusion.Asp.Net.Core.Succinctly.Mvc.Models.User> |
In this case, the output should be something like the following.

Figure 5-11: Server-Side Page Rendered Using MVC for a List
You just saw a small introduction to ASP.NET MVC. Notice that HomeController combined with the Index action handle the root domain (http://localhost:5000 in our case). But why?
To get the answer, you have to go back to the MVC configuration where we wrote this code:
Code Listing 5-15
using Microsoft.AspNetCore.Builder; |
The method app.UseMvcWithDefaultRoute() defines the default route; it is equivalent to writing the following:
Code Listing 5-16
app.UseMvc(routes => |
This part of code says to split the URL into segments, where the first is the controller, the second is the action, and the third (optional) is the parameter. If they are all missing, use the action Index of HomeController.
In fact, if you run the application again and write this URL:
http://localhost:5000/home/index
The output should be the same.
If you want to manage a URL like http://localhost:5000/products, create a ProductController with an Index action.
After seeing the general features of ASP.NET Core MVC, it is time to see two new features that are specific to the view side of ASP.NET MVC applications:
Tag Helpers are a new way of exposing server-side code that renders HTML elements. They bring the same features of HTML Razor helpers to the easier-to-use syntax of standard HTML elements.
View components can be seen as either a more powerful version of partial views or a less convoluted way to develop child actions. Let's look in detail at both of these new features.
Compared to HTML Razor helpers, Tag Helpers look like standard HTML elements—no more switching context between HTML and Razor syntax.
Let's see an example to make things a bit clearer. If you want to make an editing form with ASP.NET MVC, you have to display a textbox that takes the value from the view model, renders validation results, and so on.
Using the previous HTML Razor helpers, you would have written:
@Html.TextBoxFor(m=>m.FirstName)
But now with Tag Helpers, you can directly write <input asp-for="FirstName" /> without introducing the Razor syntax. Notice that it's just a normal HTML <input> tag enhanced with the special attribute asp-for.
It doesn't look like such a big change, but the advantage becomes clear when you add more attributes. One example of this is the class attribute.
This is how you add the class using the old HTML Razor syntax:
@Html.TextBoxFor(m=>m.Email, new { @class = "form-control" })
Using the Tag Helper, it's just this:
<input asp-for="FirstName" class="form-control" />.
Basically, you write the tag like you were writing a static HTML tag, with the addition of the special asp-for.
But this new syntax retains the support of Visual Studio IntelliSense. As soon as you start typing an HTML element that is somehow enhanced via Tag Helpers, you see in the IntelliSense menu that the tag is represented with an icon that is different from normal HTML tags.

Figure 5-12: Visual Studio IntelliSense for HTML Tags
If you then trigger the IntelliSense menu to see all the available attributes, only one has the same icon again, the asp-for attribute. Once you add this attribute and open the IntelliSense menu again, you’ll see all methods and properties of the page model.

Figure 5-13: Visual Studio IntelliSense for MVC Model
Look at the two previous screenshots carefully. You'll notice that the <input> tag has changed color. The following picture highlights the difference better.

Figure 5-14: Difference between the Two Tags
In the first line, the element is blue with attributes in blue. While in the second, the element is green with the special attribute also in green (the normal attribute is still blue). Visual Studio recognizes both normal HTML tags and attributes, and Tag Helpers. This avoids confusion when editing a view.
ASP.NET Core MVC comes with a lot of Tag Helpers, most of them are just reimplementing the same HTML Razor helpers used to edit forms, like the input, form, label, and select elements. But there are other Tag Helpers, used to manage cache, to render different HTML elements based on the environment, and to manage script fallback or CSS files. You can see many of these tag helpers used in the View\Shared\_Layout.cshtml file in the default project template. A reduced version of the file is available in the following code listing.
Code Listing 5-17
<!DOCTYPE html> |
Tag Helpers are easy to create, so it's worth seeing how to create your own. Writing a custom Tag Helper is especially useful when you want to output an HTML snippet that is long and repetitive, but changes very little from one instance to another, or when you want to somehow modify the content of an element.
As an example, you are going to create a Tag Helper that automatically creates a link by just specifying the URL.
Something that takes this:
<url>https://www.syncfusion.com/resources/techportal/ebooks</url>
And creates a working a tag, like this:
<a href="https://www.syncfusion.com/resources/techportal/ebooks">https://www.syncfusion.com/resources/techportal/ebooks</a>.
Start by creating a UrlTagHelper file inside the MVC project. A good convention is to put the file inside a TagHelpers folder.
A Tag Helper is a class that inherits from TagHelper and defines its behavior by overriding the method Process or its asynchronous counterpart ProcessAsync. These methods have two arguments:
To use a Tag Helper in the views, you have to tell both Visual Studio and the .NET Core framework where to find them. This is done by adding a reference in the _ViewImports.cshtml file.
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper "*, MvcSample"
To make sure all the basic steps are done, copy the following code into the UrlTagHelper file.
Code Listing 5-18
using Microsoft.AspNetCore.Razor.TagHelpers; |
This Tag Helper at the moment is useless. It only replaced the tag used when calling the helper from whatever it was (a URL in our example) to a tag, but it doesn't create an href attribute pointing to the specified URL. To do so, you have to read the content of the element and create a new attribute. Since the content could also be a Razor expression, the method to do so is an Async method, output.GetChildContentAsync(). You also have to change the method you implemented from Process to ProcessAsync.
The complete Tag Helper is shown in the following code listing.
Code Listing 5-19
using Microsoft.AspNetCore.Razor.TagHelpers; |
Tag Helpers can also have attributes. You can extend the URL Tag Helper to specify the target of the link. To add an attribute to a tag helper, add a property to the class. In the case of the target, you just need to add public string Target { get; set; } to the class. But having a string parameter is not a nice experience because IntelliSense doesn't show which values are allowed. You can define the property as an enum whose values are only the ones allowed for the target HTML attribute. Then you have nice IntelliSense.

Figure 5-15: HTML Property Suggestion
This is the code of the updated Tag Helper:
Code Listing 5-20
using Microsoft.AspNetCore.Razor.TagHelpers; |
Now, <url target="Blank">http://example.com</url> is rendered as <a href="http://example.com" target="_blank">http://example.com</a>.
View components are the next new, view-related feature. They are in a way similar to partial views, but they are much more powerful and used to solve different problems.
A partial view is, as the name implies, a view. It is typically used to simplify complex views by splitting them into reusable parts. Partial views have access to the view model of the parent page and don't have complex logic.
On the other hand, view components don't have access to the page model; they only operate on the arguments that are passed to them, and they are composed by both view and class with the logic.
If you used a child action in previous versions of ASP.NET MVC, they more or less solved the same problem in a more elegant way, as their execution didn’t go through the whole ASP.NET MVC execution pipeline starting from the routing.
Typically, view controllers are used to render reusable pieces of pages that also include logic that might involve hitting a database—for example sidebars, menus, conditional login panels, etc.
As mentioned, a view component is made of two parts. The class containing the logic extends the ViewComponent class and must implement either the Invoke or the InvokeAsync method. This returns IViewComponentResult with the model that has to be passed to the view. Conventionally, all view components are located in a folder named ViewComponents in the root of the project.
The view is just like any other view. It receives the model passed by the component class that is accessed via the @Model variable. The view for a view component has to be saved in the Views\Shared\Components\<component-name>\Default.cshtml file.
As example, let's build a view component that shows the sidebar of a blog. The component class just calls an external repository to fetch the list of links.
Code Listing 5-21
using System.Threading.Tasks; |
Notice that it receives the dependency in the constructor, as shown for controllers in ASP.NET Core MVC. In this case, since the operation of retrieving the links goes to a database, you implement the Async version of the component.
The next step is implementing the view. Nothing special to mention here, just a simple view that renders a list of links.
Code Listing 5-22
@model IEnumerable<MvcSample.Model.Link> |
The important fact to remember is where this view is located. Following convention, it must be saved as Views\Shared\Components\Sidebar\Default.cshtml.
And now it’s time to include the component into a view. This is done by simply calling the view component using the Razor syntax.
Code Listing 5-23
@await Component.InvokeAsync("SideBar", new {max = 5}) |
This is a bit convoluted, especially the need to create an anonymous class just for passing the arguments. But there is also another way of calling a view component as if it were a tag helper. Starting from ASP.NET Core 1.1, all view components are also registered as Tag Helpers with the prefix vc.
Code Listing 5-24
<vc:side-bar max="5"></vc:side-bar> |
Apart from being easier to write, this also implements IntelliSense in the HTML editor.

Figure 5-16: IntelliSense for Tag Helpers
ASP.NET Core comes with a rewritten MVC framework, improved from the previous version and aimed at being the unified programming model for any kind of web-based interaction.
You’ve seen the cool new features introduced for simplifying the development of views. This is the last chapter that explains coding. The next two chapters are more about tooling, showing how to deploy apps and how to develop on Mac without Visual Studio.