<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>asp.net tips &#8211; ASP.NET Hosting Reviews and Guides</title>
	<atom:link href="https://topreviewhostingasp.net/tag/asp-net-tips/feed/" rel="self" type="application/rss+xml" />
	<link>https://topreviewhostingasp.net</link>
	<description>ASP.NET Hosting &#124; Reviews &#124; Tips &#38; Tutorial</description>
	<lastBuildDate>Wed, 28 Apr 2021 05:35:42 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://topreviewhostingasp.net/wp-content/uploads/2017/01/cropped-trhaico-32x32.png</url>
	<title>asp.net tips &#8211; ASP.NET Hosting Reviews and Guides</title>
	<link>https://topreviewhostingasp.net</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Know Further About ModelState in ASP.NET 5.0</title>
		<link>https://topreviewhostingasp.net/know-further-about-modelstate-in-asp-net-5-0/</link>
					<comments>https://topreviewhostingasp.net/know-further-about-modelstate-in-asp-net-5-0/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Wed, 28 Apr 2021 05:21:39 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net 5]]></category>
		<category><![CDATA[asp net 5 modelstate]]></category>
		<category><![CDATA[asp net 5 tips]]></category>
		<category><![CDATA[asp net 5 tutorial]]></category>
		<category><![CDATA[asp.net tips]]></category>
		<category><![CDATA[asp.net tutorial]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2956</guid>

					<description><![CDATA[In this post, we&#8217;re going to explain what the ModelState is, and what it is used for. We&#8217;ll also show how to use it to validate our POSTed inputs, and do simple custom validation. Here we go! What is the ModelState? In short, the ModelState is a collection of name and value pairs that are submitted to the server [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>In this post, we&#8217;re going to explain what the <code>ModelState</code> is, and what it is used for. We&#8217;ll also show how to use it to validate our POSTed inputs, and do simple custom validation. Here we go!</p>



<h2 class="wp-block-heading" id="what-is-the-modelstate">What is the ModelState?</h2>



<p>In short, the <code>ModelState</code> is a collection of name and value pairs that are submitted to the server during a POST. It also contains error messages about each name-value pair, if any are found.</p>



<p><code>ModelState</code> is a property of a <code>Controller</code> instance, and can be accessed from any class that inherits from <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controller?view=aspnetcore-5.0">Microsoft.AspNetCore.Mvc.Controller</a>.</p>



<p>The <code>ModelState</code> has two purposes: to store and submit POSTed name-value pairs, and to store the validation errors associated with each value.</p>



<p>All right, enough of the boring explanation. It&#8217;s code time!</p>



<h2 class="wp-block-heading" id="the-sample-project">The Sample Project</h2>



<p>You can use <a href="https://github.com/exceptionnotfound/ModelStateAspNet5Demo">sample project on Github</a>.</p>



<h2 class="wp-block-heading" id="setup">Setup</h2>



<p>Let&#8217;s start writing the code we need to demonstrate how the <code>ModelState</code> works in ASP.NET 5 MVC. We will begin by creating a straightforward view model, <code>AddMovieVM</code>:</p>



<pre class="wp-block-code"><code>namespace ModelStateCoreDemo.ViewModels
{
    public class AddMovieVM
    {
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public int RuntimeMinutes { get; set; }
    }
}</code></pre>



<p>We will also create a corresponding <code>Add.cshtml</code> view in the folder Views/Movie:</p>



<pre class="wp-block-code"><code>@model ModelStateCoreDemo.ViewModels.AddMovieVM

&lt;h2&gt;Add Movie&lt;/h2&gt;

&lt;form asp-action="AddPost" asp-controller="Movie" method="post"&gt;
    &lt;div&gt;
        &lt;div&gt;
            &lt;label asp-for="Title"&gt;&lt;/label&gt;
            &lt;input type="text" asp-for="Title" /&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label asp-for="Description"&gt;&lt;/label&gt;
            &lt;input type="text" asp-for="Description" /&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label asp-for="ReleaseDate"&gt;&lt;/label&gt;
            &lt;input type="date" asp-for="ReleaseDate" /&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label asp-for="RuntimeMinutes"&gt;&lt;/label&gt;
            &lt;input type="number" asp-for="RuntimeMinutes" /&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;input type="submit" value="Save" /&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt; </code></pre>



<p>Lastly, we create a <code>MovieController</code> class with two actions:</p>



<pre class="wp-block-code"><code>using Microsoft.AspNetCore.Mvc;
using ModelStateCoreDemo.ViewModels;

public class MovieController : Controller
{
    [HttpGet("movies/add")]
    public IActionResult Add()
    {
        AddMovieVM model = new AddMovieVM();
        return View(model);
    }

    [HttpPost("movies/add/post")]
    public IActionResult AddPost(AddMovieVM model)
    {
        if(!ModelState.IsValid)
        {
            return View("Add", model);
        }

        return RedirectToAction("Index");
    }
}</code></pre>



<p>When we submit our Add form to the POST action, all of the values we entered on the view will show up in the correct properties in the <code>AddMovieVM</code> instance. But how did they get there?</p>



<h2 class="wp-block-heading" id="peeking-into-the-modelstate">Peeking Into the ModelState</h2>



<p>Let&#8217;s take a peek at the rendered HTML for the Add page:</p>



<pre class="wp-block-code"><code>&lt;h2&gt;Add Movie&lt;/h2&gt;

&lt;form method="post" action="/movies/add"&gt;
    &lt;div&gt;
        &lt;div&gt;
            &lt;label for="Title"&gt;Title&lt;/label&gt;
            &lt;input type="text" 
                   id="Title" 
                   name="Title" 
                   value=""&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label for="ReleaseDate"&gt;ReleaseDate&lt;/label&gt;
            &lt;input type="date" 
                   id="ReleaseDate" 
                   name="ReleaseDate" 
                   value="0001-01-01"&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label for="RuntimeMinutes"&gt;RuntimeMinutes&lt;/label&gt;
            &lt;input type="number" 
                   id="RuntimeMinutes" 
                   name="RuntimeMinutes" 
                   value="0"&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;input type="submit" value="Save"&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt; </code></pre>



<p>When this page is POSTed to the server, all values in <code>&lt;input&gt;</code> tags will be submitted as name-value pairs.</p>



<p>At the point when ASP.NET 5 MVC receives a POST action, it takes all of the name-value pairs and adds them as individual instances of <code>ModelStateEntry</code> to an instance of <code>ModelStateDictionary</code>. Both <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.modelstateentry?view=aspnetcore-5.0">ModelStateEntry</a> and <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.modelstatedictionary?view=aspnetcore-5.0">ModelStateDictionary</a> have pages in Microsoft&#8217;s documentation.</p>



<p>In Visual Studio, we can use the Locals window to show what exactly this looks like:</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="907" height="486" class="wp-image-2957" src="https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_1.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_1.png 907w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_1-300x161.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_1-768x412.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_1-50x27.png 50w" sizes="(max-width: 907px) 100vw, 907px" /></figure>



<p>We can see from the <code>Values</code> property of the <code>ModelState</code> that there are three name-value pairs: one each for <code>Title</code>, <code>ReleaseDate</code>, and <code>RuntimeMinutes</code>.</p>



<p>Each of the items in the results for the <code>Values</code> is of type <code>ModelStateEntry</code>. But what exactly is this?</p>



<h2 class="wp-block-heading" id="what-s-in-the-modelstateentry">What&#8217;s In the ModelStateEntry?</h2>



<p>Here&#8217;s what those same input values look like, taken from the same debugger session.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="907" height="483" class="wp-image-2958" src="https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_2.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_2.png 907w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_2-300x160.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_2-768x409.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_2-50x27.png 50w" sizes="(max-width: 907px) 100vw, 907px" /></figure>



<p>You can see that each <code>ModelStateEntry</code> contains properties like <code>RawValue</code>, which holds the raw value that was submitted, and <code>Key</code>, which holds the name of said value. ASP.NET 5 MVC creates all of these instances for us automatically when we submit a POST action that has associated data. ASP.NET 5 MVC is therefore making what was a complicated set of data into easier-to-use instances.</p>



<p>There are two important functions of the <code>ModelState</code> that we still need to discuss: errors and validation.</p>



<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://www.asphostportal.com"><img decoding="async" width="300" height="271" class="wp-image-2953 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2021/04/ahp-banner-aspnet-mvc-01.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/04/ahp-banner-aspnet-mvc-01.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/ahp-banner-aspnet-mvc-01-50x45.png 50w" sizes="(max-width: 300px) 100vw, 300px" /></a></figure>
</div>



<h2 class="wp-block-heading" id="validation-errors-in-the-modelstate">Validation Errors in the ModelState</h2>



<p>Let&#8217;s make a quick modification to our <code>AddMovieVM</code> class so that we are now implementing validation on its fields.</p>



<pre class="wp-block-code"><code>public class AddMovieVM
{
    [Required(ErrorMessage = "The Title cannot be blank.")]
    [DisplayName("Title: ")]
    public string Title { get; set; }

    [DisplayName("Release Date: ")]
    public DateTime ReleaseDate { get; set; }

    [Required(ErrorMessage = "The Runtime Minutes cannot be blank.")]
    [Range(1, int.MaxValue, 
           ErrorMessage = "The Runtime Minutes must be greater than 0.")]
    [DisplayName("Runtime Minutes: ")]
    public int RuntimeMinutes { get; set; }
}
</code></pre>



<p>We have added validation to these fields using the <code>[Required]</code> and <code>[Range]</code> validation attributes, as well as specifying the name to use in <code>&lt;label&gt;</code> tags with the <code>[DisplayName]</code> attribute. If the <code>Title</code>, the <code>Description</code>, or the <code>RuntimeMinutes</code> field fails validation, we need to show an error message.</p>



<p>To do that, we must make some changes to our view; we will need to add a <code>&lt;span&gt;</code> tag with the property <code>asp-validation-for</code> set for each input:</p>



<pre class="wp-block-code"><code>@model ModelStateCoreDemo.ViewModels.AddMovieVM

&lt;h2&gt;Add Movie&lt;/h2&gt;

&lt;form asp-action="AddPost" asp-controller="Movie" method="post"&gt;
    &lt;div&gt;
        &lt;div&gt;
            &lt;label asp-for="Title"&gt;&lt;/label&gt;
            &lt;input type="text" asp-for="Title"/&gt;
            &lt;span asp-validation-for="Title"&gt;&lt;/span&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label asp-for="ReleaseDate"&gt;&lt;/label&gt;
            &lt;input type="date" asp-for="ReleaseDate" /&gt;
            &lt;span asp-validation-for="ReleaseDate"&gt;&lt;/span&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label asp-for="RuntimeMinutes"&gt;&lt;/label&gt;
            &lt;input type="number" asp-for="RuntimeMinutes" /&gt;
            &lt;span asp-validation-for="RuntimeMinutes"&gt;&lt;/span&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;input type="submit" value="Save"/&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt; </code></pre>



<p>The <code>asp-validation-for</code> property will render the validation errors message in the specified <code>&lt;span&gt;</code> element, with some default CSS already applied.</p>



<p>Let&#8217;s take a look at what happens to our collection of <code>ModelStateEntry</code> instances when an invalid object is submitted to the server:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="906" height="484" class="wp-image-2959" src="https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_3.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_3.png 906w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_3-300x160.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_3-768x410.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_3-50x27.png 50w" sizes="(max-width: 906px) 100vw, 906px" /></figure>



<p>Note that the <code>IsValid</code> property of the <code>ModelState</code> is now <code>false</code>, and the <code>ValidationState</code> property of the invalid <code>ModelStateEntry</code> instances is now <code>Invalid</code>.</p>



<p>When ASP.NET 5 MVC creates the model state for the submitted values, it also iterates through each property in the view model and validates said property using the attributes associated to that property. In certain cases, attributes are implicitly evaluated (in our particular case, <code>ReleaseDate</code> has an implicit <code>[Required]</code> attribute because its type is <code>DateTime</code> and therefore cannot be blank).</p>



<p>If any errors are found, they are added to the <code>Errors</code> property of each <code>ModelStateEntry</code>. There is also a property <code>ErrorCount</code> on the <code>ModelState</code> that shows all errors found during the validation. If errors exist for a given POSTed value, the <code>ValidationState</code> of that property becomes <code>Invalid</code>.</p>



<p>In this case, because at least one of the <code>ModelStateEntry</code> instances has an error, the <code>IsValid</code> property of <code>ModelState</code> is now <code>false</code>.</p>



<p>What all of this means is merely this: we are using ASP.NET 5 MVC the way it was intended to be used. The <code>ModelState</code> stores submitted values, calculates the errors associated with each, and allows our controllers to check for said errors as well as the <code>IsValid</code> flag. In many scenarios, this is all we need, and all of it happens behind the scenes!</p>



<h2 class="wp-block-heading" id="custom-validation">Custom Validation</h2>



<p>There are times when we need more complex validation than ASP.NET 5 provides natively.</p>



<p>Let&#8217;s pretend that we now need a new field, <code>Description</code>, for each movie. Let&#8217;s also pretend that in addition to not allowing <code>Description</code> to be blank, it also cannot be exactly the same as the <code>Title</code>.</p>



<p>First, we can add the <code>Description</code> field to the view model:</p>



<pre class="wp-block-code"><code>public class AddMovieVM
{
    [Required(ErrorMessage = "The Title cannot be blank.")]
    [DisplayName("Title: ")]
    public string Title { get; set; }

    [Required(ErrorMessage = "The Description cannot be blank.")]
    [DisplayName("Description: ")]
    public string Description { get; set; }

    [DisplayName("Release Date: ")]
    public DateTime ReleaseDate { get; set; }

    [Required(ErrorMessage = "The Runtime Minutes cannot be blank.")]
    [Range(1, int.MaxValue, 
           ErrorMessage = "The Runtime Minutes must be greater than 0.")]
    [DisplayName("Runtime Minutes: ")]
    public int RuntimeMinutes { get; set; }
}</code></pre>



<p>We can also add it to the view:</p>



<pre class="wp-block-code"><code>@model ModelStateCoreDemo.ViewModels.AddMovieVM

&lt;h2&gt;Add Movie&lt;/h2&gt;

&lt;form asp-action="AddPost" asp-controller="Movie" method="post"&gt;
    &lt;div&gt;
        &lt;div&gt;
            &lt;label asp-for="Title"&gt;&lt;/label&gt;
            &lt;input type="text" asp-for="Title" /&gt;
            &lt;span asp-validation-for="Title"&gt;&lt;/span&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label asp-for="Description"&gt;&lt;/label&gt;
            &lt;input type="text" asp-for="Description" /&gt;
            &lt;span asp-validation-for="Description"&gt;&lt;/span&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label asp-for="ReleaseDate"&gt;&lt;/label&gt;
            &lt;input type="date" asp-for="ReleaseDate" /&gt;
            &lt;span asp-validation-for="ReleaseDate"&gt;&lt;/span&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;label asp-for="RuntimeMinutes"&gt;&lt;/label&gt;
            &lt;input type="number" asp-for="RuntimeMinutes" /&gt;
            &lt;span asp-validation-for="RuntimeMinutes"&gt;&lt;/span&gt;
        &lt;/div&gt;
        &lt;div&gt;
            &lt;input type="submit" value="Save" /&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt; </code></pre>



<p>When the form is POSTed, we can do custom validation in our controllers. To check that the <code>Description</code> does not exactly match the <code>Title</code>, we can modify the POST action on our <code>MovieController</code> class like so:</p>



<pre class="wp-block-code"><code>public class MovieController : Controller
{
    //... Other methods

    [HttpPost("movies/add/post")]
    public IActionResult AddPost(AddMovieVM model)
    {
        if(model.Title == model.Description)
        {
            ModelState.AddModelError("description", 
                "The Description cannot exactly match the Title.");
        }

        if(!ModelState.IsValid)
        {
            return View("Add", model);
        }

        return RedirectToAction("Index");
    }
}</code></pre>



<p>Which will show the error next to the input for <code>Description</code>:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="626" height="240" class="wp-image-2960 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_4.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_4.png 626w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_4-300x115.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/04/image_4-50x19.png 50w" sizes="(max-width: 626px) 100vw, 626px" /></figure>



<h2 class="wp-block-heading" id="summary">Summary</h2>



<p>In ASP.NET 5 MVC, the <code>ModelState</code> property of a controller represents the submitted values, and validation errors in those values if such errors exist, during a POST action.</p>



<p>During the POST, the values submitted can be validated, and the validation process uses attributes defined by .NET like <code>[Required]</code> and <code>[Range]</code>. We can do simple custom validation server-side by modifying our controllers.</p>



<p>On views, the <code>asp-validation-for</code> property on a <code>&lt;span&gt;</code> element will show an error message for a specific property of the view model.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/know-further-about-modelstate-in-asp-net-5-0/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Using ASP.NET Core to Find Controllers in Your App</title>
		<link>https://topreviewhostingasp.net/using-asp-net-core-to-find-controllers-in-your-app/</link>
					<comments>https://topreviewhostingasp.net/using-asp-net-core-to-find-controllers-in-your-app/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 16 Mar 2021 03:57:20 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net controller]]></category>
		<category><![CDATA[ASP.NET Hosting]]></category>
		<category><![CDATA[asp.net tips]]></category>
		<category><![CDATA[asp.net tutorial]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2942</guid>

					<description><![CDATA[In this post I describe application parts and how ASP.NET Core uses them to find the controllers in your app. I then show how you can retrieve the list at runtime for debugging purposes. Debugging a missing controller A while ago I was converting an ASP.NET application to ASP.NET Core. The solution had many class [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>In this post I describe application parts and how ASP.NET Core uses them to find the controllers in your app. I then show how you can retrieve the list at runtime for debugging purposes.</p>



<h2 class="wp-block-heading">Debugging a missing controller</h2>



<p>A while ago I was converting an ASP.NET application to ASP.NET Core. The solution had many class library projects, where each project represented a module or vertical slice of the application. These modules contained everything for that feature: the database code, the domain, and the Web API controllers. There was then a &#8220;top level&#8221; application that referenced all these modules and served the requests.</p>



<p>As the whole solution was based on Katana/Owin and used Web API controllers exclusively, it wasn&#8217;t too hard to convert it to ASP.NET Core. But, of course, there were bugs in the conversion process. One thing that had me stumped for a while was why the controllers from some of the modules didn&#8217;t seem to be working. All of the requests to certain modules were returning 404s.</p>



<p>There were a few possibilities in my mind for what was going wrong:</p>



<ol>
<li>There was a routing issue, so requests meant for the controllers were not reaching them</li>
<li>There was a problem with the controllers themselves, meaning they were generating 404s</li>
<li>The ASP.NET Core app wasn&#8217;t aware of the controllers in the module at all.</li>
</ol>



<p>My gut feeling was the problem was either 1 or 3, but I needed a way to check. The solution I present in this post let me rule out point 3, by listing all the <code>ApplicationPart</code>s and controllers the app was aware of.</p>



<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://www.asphostportal.com"><img loading="lazy" decoding="async" width="300" height="271" class="wp-image-2584 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01-50x45.png 50w" sizes="(max-width: 300px) 100vw, 300px" /></a></figure>
</div>



<h2 class="wp-block-heading">What are application parts?</h2>



<p>Application Parts allow you to share the same resources (controllers, Razor Pages etc) between multiple apps. If you&#8217;re familiar with <a href="https://docs.microsoft.com/en-us/aspnet/core/razor-pages/ui-class?view=aspnetcore-3.1&amp;tabs=visual-studio">Razor Class Libraries</a>, then think of application parts as being the abstraction behind it.</p>



<p>One application part implementation is <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.applicationparts.assemblypart?view=aspnetcore-3.1">an <code>AssemblyPart</code></a> which is an application part associated with an assembly. This is the situation I had in the app I described previously &#8211; each of the module projects was compiled into a separate <code>Assembly</code>, and then added to the application as application parts.</p>



<p>You can add application parts in <code>ConfigureServices</code> when you configure MVC. The current assembly is added automatically, but you can add additional application parts too. The example below adds the assembly that contains <code>TestController</code> (which resides in a different project) as an application part.</p>



<pre class="wp-block-code"><code>public void ConfigureServices(IServiceCollection services)
{
    services
        .AddControllers()
        .AddApplicationPart(typeof(TestController).Assembly);
}</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>Note that in ASP.NET Core 3.x, when you compile an assembly that references ASP.NET Core, </em><a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.applicationparts.applicationpartattribute?view=aspnetcore-3.1">an assembly attribute is added to the output, <code>[ApplicationPart]</code></a><em>. ASP.NET Core 3.x apps look for this attribute on referenced assemblies and registers them as application parts automatically, so the code above isn&#8217;t necessary.</em></p>
</blockquote>



<p>We&#8217;ve covered how you register application parts, but how do we debug when things go wrong?</p>



<h2 class="wp-block-heading">Providing features with the ApplicationPartManager</h2>



<p>When you add an application part (or when ASP.NET Core adds it automatically), it&#8217;s added to the <code>ApplicationPartManager</code>. <a href="https://github.com/dotnet/aspnetcore/blob/6255c1ed960f5277d2e96ac2d0968c2c7e844ce2/src/Mvc/Mvc.Core/src/ApplicationParts/ApplicationPartManager.cs">This class</a> is responsible for keeping track of all the application parts in the app, and for populating various <em>features</em> based on the registered parts, in conjunction with registered <em>feature providers</em>.</p>



<p>There are a variety of <em>features</em> used in MVC, such as the <code>ControllerFeature</code> and <code>ViewsFeature</code> for example. <a href="https://github.com/dotnet/aspnetcore/blob/6255c1ed960f5277d2e96ac2d0968c2c7e844ce2/src/Mvc/Mvc.Core/src/Controllers/ControllerFeature.cs">The <code>ControllerFeature</code> (shown below)</a> contains a list of all the controllers available to an application, across all of the registered application parts.</p>



<pre class="wp-block-code"><code>public class ControllerFeature
{
    public IList&lt;TypeInfo&gt; Controllers { get; } = new List&lt;TypeInfo&gt;();
}</code></pre>



<p>The list of controllers is obtained <a href="https://github.com/dotnet/aspnetcore/blob/6255c1ed960f5277d2e96ac2d0968c2c7e844ce2/src/Mvc/Mvc.Core/src/Controllers/ControllerFeatureProvider.cs">by using the <code>ControllerFeatureProvider</code></a>. <a href="https://github.com/dotnet/aspnetcore/blob/6255c1ed960f5277d2e96ac2d0968c2c7e844ce2/src/Mvc/Mvc.Core/src/ApplicationParts/IApplicationFeatureProviderOfT.cs">This class implements the <code>IApplicationFeatureProvider&lt;T&gt;</code> interface</a>, which, when given a list of application parts, populates an instance of <code>ControllerFeature</code> with all the controllers it finds.</p>



<pre class="wp-block-code"><code>public class ControllerFeatureProvider : IApplicationFeatureProvider&lt;ControllerFeature&gt;
{
    public void PopulateFeature(IEnumerable&lt;ApplicationPart&gt; parts, ControllerFeature feature)
    {
        <em>// Loop through all the application parts</em>
        foreach (var part in parts.OfType&lt;IApplicationPartTypeProvider&gt;())
        {
            <em>// Loop through all the types in the application part</em>
            foreach (var type in part.Types)
            {
                <em>// If the type is a controller (and isn't already added) add it to the list</em>
                if (IsController(type) &amp;&amp; !feature.Controllers.Contains(type))
                {
                    feature.Controllers.Add(type);
                }
            }
        }
    }

    protected virtual bool IsController(TypeInfo typeInfo) =&gt; { <em>/* Elided for brevity*/</em> }
}
</code></pre>



<p>The <code>ApplicationPartManager</code> exposes <a href="https://github.com/dotnet/aspnetcore/blob/6255c1ed960f5277d2e96ac2d0968c2c7e844ce2/src/Mvc/Mvc.Core/src/ApplicationParts/ApplicationPartManager.cs#L40-L50">a <code>PopulateFeature</code> method which calls all the appropriate feature providers for a given feature</a>:</p>



<pre class="wp-block-code"><code>public class ApplicationPartManager
{
    <em>// The list of application parts</em>
    public IList&lt;ApplicationPart&gt; ApplicationParts { get; } = new List&lt;ApplicationPart&gt;();

    <em>// The list of feature providers for the various possible features</em>
    public IList&lt;IApplicationFeatureProvider&gt; FeatureProviders { get; } =
            new List&lt;IApplicationFeatureProvider&gt;();


    <em>// Populate the feature of type TFeature</em>
    public void PopulateFeature&lt;TFeature&gt;(TFeature feature)
    {
        foreach (var provider in FeatureProviders.OfType&lt;IApplicationFeatureProvider&lt;TFeature&gt;&gt;())
        {
            provider.PopulateFeature(ApplicationParts, feature);
        }
    }</code></pre>



<p>That covers all the background for <code>ApplicationPartManager</code> and features.</p>



<h2 class="wp-block-heading">Listing all the Application parts and controllers added to an application</h2>



<p>To quickly work out whether my <code>404</code> problem was due to routing or missing controllers, I needed to interrogate the <code>ApplicationPartManager</code>. If the application parts and controllers for the problematic modules were missing, then that was the problem; if they were present, then it was probably some sort of routing issue!</p>



<p>To debug the issue I wrote a quick <code>IHostedService</code> that logs the application parts added to an application, along with all of the controllers discovered.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>I used an <code>IHostedService</code> because it runs after application part discovery, and only executes once on startup.</p>
</blockquote>



<p>The example below takes an <code>ILogger</code> and the <code>ApplicationPartManager</code> as dependencies. It then lists the names of the application parts, populates an instance of the <code>ControllerFeature</code>, and lists all the controllers known to the app. These are written to a log message which can be safely inspected</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/app-parts?view=aspnetcore-3.1#display-available-features">A similar example in the documentation</a><em> exposes this information via a Controller, which seems like a bit of a bad idea to me!</em></p>
</blockquote>



<pre class="wp-block-code"><code>public class ApplicationPartsLogger : IHostedService
{
    private readonly ILogger&lt;ApplicationPartsLogger&gt; _logger;
    private readonly ApplicationPartManager _partManager;

    public ApplicationPartsLogger(ILogger&lt;ApplicationPartsLogger&gt; logger, ApplicationPartManager partManager)
    {
        _logger = logger;
        _partManager = partManager;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        <em>// Get the names of all the application parts. This is the short assembly name for AssemblyParts</em>
        var applicationParts = _partManager.ApplicationParts.Select(x =&gt; x.Name);

        <em>// Create a controller feature, and populate it from the application parts</em>
        var controllerFeature = new ControllerFeature();
        _partManager.PopulateFeature(controllerFeature);

        <em>// Get the names of all of the controllers</em>
        var controllers = controllerFeature.Controllers.Select(x =&gt; x.Name);

        <em>// Log the application parts and controllers</em>
        _logger.LogInformation("Found the following application parts: '{ApplicationParts}' with the following controllers: '{Controllers}'",
            string.Join(", ", applicationParts), string.Join(", ", controllers));

        return Task.CompletedTask;
    }

    <em>// Required by the interface</em>
    public Task StopAsync(CancellationToken cancellationToken) =&gt; Task.CompletedTask;
}</code></pre>



<p>All that remains is to register the hosted service in <code>Startup.ConfigureServices</code>:</p>



<pre class="wp-block-code"><code>public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddHostedService&lt;ApplicationPartsLogger&gt;();
}</code></pre>



<p>Below is example log message, in which an API project (<em>ApplicationPartsDebugging.Api</em>) references a class library (<em>ApplicationPartsDebugging.Controllers</em>) which contains a controller, <code>TestController</code>.</p>



<pre class="wp-block-code"><code>info: ApplicationPartsDebugging.Api.ApplicationPartsLogger[0]
      Found the following application parts: 'ApplicationPartsDebugging.Api, ApplicationPartsDebugging.Controllers' 
      with the following controllers: 'WeatherForecastController, TestController'</code></pre>



<p>Both the API app and the class library are referenced as application parts, and controllers from both application parts are available.</p>



<p>And yes, this was exactly the problem I had during my conversion, I&#8217;d failed to register one of the modules as an application part, shown by it&#8217;s absence from my log message!</p>



<h2 class="wp-block-heading" id="summary">Summary</h2>



<p>In this post I described a problem I faced when converting an application to ASP.NET Core &#8211; the controllers from a referenced project could not be found. ASP.NET Core looks for controllers, views, and other features in <em>application parts</em> that it knows about. You can add additional application parts to an ASP.NET Core manually, though ASP.NET Core 3.x will generally handle this for you automatically. To debug my problem I created an <code>ApplicationPartsLogger</code> that lists all the registered application parts for an app. This allows you to easily spot when an expected assembly is missing.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/using-asp-net-core-to-find-controllers-in-your-app/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Using IHttpClientFactory in ASP.NET Core</title>
		<link>https://topreviewhostingasp.net/using-ihttpclientfactory-in-asp-net-core/</link>
					<comments>https://topreviewhostingasp.net/using-ihttpclientfactory-in-asp-net-core/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 23 Feb 2021 03:16:00 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp.net core]]></category>
		<category><![CDATA[asp.net core tips]]></category>
		<category><![CDATA[asp.net core tutorial]]></category>
		<category><![CDATA[asp.net tips]]></category>
		<category><![CDATA[asp.net tutorial]]></category>
		<category><![CDATA[httpclient asp net core]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2928</guid>

					<description><![CDATA[In today’s post, we will see how to create named HTTPClient requests using HTTPClientFactory in .NET Core or ASP.NET Core. Create a Named HTTPClient Create an ASP.NET Core Project Let’s look at step by step to understand and create named HTTPClient approach where we shall be creating HTTPClient request object using HTTPClientFactory. Interface IHTTPClientFactory  can be injected in Controller [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>In today’s post, we will see how to create named HTTPClient requests using <strong>HTTPClientFactory </strong>in .NET Core or ASP.NET Core.</p>



<h2 class="wp-block-heading">Create a Named HTTPClient</h2>



<p><strong>Create an ASP.NET Core Project</strong></p>



<figure class="wp-block-image size-large"><img decoding="async" class="wp-image-2929" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/image_1.jpeg" alt="" /></figure>



<p>Let’s look at step by step to understand and create named HTTPClient approach where we shall be creating HTTPClient request object using HTTPClientFactory.</p>



<p>Interface <strong>IHTTPClientFactory  </strong>can be injected in Controller or any other class as needed using Constructor injection as below,</p>



<figure class="wp-block-image size-large"><img decoding="async" class="wp-image-2930" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/image_2.jpeg" alt="" /></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>Add using namespace ‘System.Net.Http’ in the code to access HTTPClient and IHTTPClientFactory </em></p>
</blockquote>



<p>Please update the <strong>ConfigureServices </strong>method in Startup.cs as below,</p>



<p>Here in below example, we are creating two types of Named client,</p>



<ul>
<li><strong>AccountClient</strong> – This client is configured for AccountSpecific request and accept ‘<strong>application/json</strong>‘ as <strong>Content-type</strong></li>
<li><strong>PayBillClient</strong> – This client is configured for Payment and Bill request and accept ‘<strong>application/xml</strong>‘ as <strong>Content-type</strong>. It also configured with security using the <strong>BasicAuthentication </strong>scheme.</li>
</ul>



<pre class="wp-block-code"><code>public void ConfigureServices(IServiceCollection services)
       {
           services.AddControllers();
           services.AddHttpClient("AccountClient", c =&gt;
           {
               c.BaseAddress = new Uri(Configuration.GetValue&lt;string&gt;("AccountURL"));
               // Account API ContentType
               c.DefaultRequestHeaders.Add("Accept", "application/json");
           });
           services.AddHttpClient("PayBillClient", c =&gt;
           {
               c.BaseAddress = new Uri(Configuration.GetValue&lt;string&gt;("PayBillURL"));
               // Account API ContentType
               c.DefaultRequestHeaders.Add("Accept", "application/xml");
           });
       }</code></pre>



<p>Below is the client-side code base for named HTTPClient.</p>



<p>Here we specify the name of the HTTPClient request using an overloaded method <strong>CreateClient(“client name”)</strong>.</p>



<pre class="wp-block-code"><code>[HttpGet]
        public async Task&lt;IActionResult&gt; OnGet()
        {
            var uri = new Uri("https://localhost:44364/account");
            var client = _clientFactory.CreateClient("AccountClient");
            var response = await client.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                return Ok(response.Content.ReadAsStreamAsync().Result);
            }
            else
            {
                return StatusCode(500, "Somthing Went Wrong! Error Occured");
            }
        }</code></pre>



<p>Similarly, other named <strong>HTTPClient </strong>for “<strong>PayBillClient</strong>” can be created as below,</p>



<pre class="wp-block-code"><code>var client = _clientFactory.CreateClient("PayBillClient");</code></pre>



<p>As we understood above HTTPClientFactory lets you DI inject the HTTPClient objects using an explicit Dependency Injection principle(DI).</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>This technique can be used configure multiple HTTPClients request with custom configuration of </em><strong>Policy, Security </strong><em>and </em><strong>delegates </strong><em>as required.</em></p>
</blockquote>



<p>This technique lets you control the lifetime management of HTTPClient instances through the API pipeline itself.</p>



<p>With this technique, we are able to centralize multiple clients with specific configurations like using network credentials, specific headers or security tokens as needed.</p>



<p>That’s All, Happy coding !!. Please sound off your comments below.</p>



<h2 class="wp-block-heading">Summary</h2>



<p>In this article, we looked at how to use HTTPClientFactory for creating <strong>Named HTTPClient </strong>request object to invoke HTTP services in ASP.NET Core. This technique also lets you control custom clients based on the required policy and delegates.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/using-ihttpclientfactory-in-asp-net-core/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Using Mailkit to Send Email ASP.NET Core 3.1</title>
		<link>https://topreviewhostingasp.net/using-mailkit-to-send-email-asp-net-core-3-1/</link>
					<comments>https://topreviewhostingasp.net/using-mailkit-to-send-email-asp-net-core-3-1/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 15 Dec 2020 04:23:53 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net core send email]]></category>
		<category><![CDATA[asp.net core tips]]></category>
		<category><![CDATA[asp.net core tutorial]]></category>
		<category><![CDATA[asp.net tips]]></category>
		<category><![CDATA[mailkit asp net core]]></category>
		<category><![CDATA[using mailkit]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2829</guid>

					<description><![CDATA[This post is an example how to send email in Asp.net Core 3.1 using Mailkit. I assume that you have downloaded it and install it on your server. How to Send HTML Email in ASP.NET Core This code sends a simple HTML email using the Ethereal free SMTP testing service, you can create a free test account [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>This post is an example how to send email in Asp.net Core 3.1 using <a href="https://www.nuget.org/packages/MailKit/">Mailkit</a>. I assume that you have downloaded it and install it on your server.</p>



<h2 class="wp-block-heading">How to Send HTML Email in ASP.NET Core</h2>



<p>This code sends a simple HTML email using the <em>Ethereal</em> free SMTP testing service, you can create a free test account in one click at <a href="https://ethereal.email/" target="_blank" rel="noreferrer noopener">https://ethereal.email/</a> and copy the username and password from below the title <em>SMTP configuration</em>. See instructions below for using different SMTP providers such as Gmail and Hotmail.</p>



<pre class="wp-block-code"><code>// create email message
var email = new MimeMessage();
email.From.Add(MailboxAddress.Parse("from_address@example.com"));
email.To.Add(MailboxAddress.Parse("to_address@example.com"));
email.Subject = "Test Email Subject";
email.Body = new TextPart(TextFormat.Html) { Text = "&lt;h1&gt;Example HTML Message Body&lt;/h1&gt;" };

// send email
using var smtp = new SmtpClient();
smtp.Connect("smtp.ethereal.email", 587, SecureSocketOptions.StartTls);
smtp.Authenticate("[USERNAME]", "[PASSWORD]");
smtp.Send(email);
smtp.Disconnect(true);</code></pre>



<h2 class="wp-block-heading">How to Send Plain Text Email in ASP.NET Core</h2>



<p>This code sends the same email as above with a plain text body.</p>



<pre class="wp-block-code"><code>// create email message
var email = new MimeMessage();
email.From.Add(MailboxAddress.Parse("from_address@example.com"));
email.To.Add(MailboxAddress.Parse("to_address@example.com"));
email.Subject = "Test Email Subject";
email.Body = new TextPart(TextFormat.Plain) { Text = "Example Plain Text Message Body" };

// send email
using var smtp = new SmtpClient();
smtp.Connect("smtp.ethereal.email", 587, SecureSocketOptions.StartTls);
smtp.Authenticate("[USERNAME]", "[PASSWORD]");
smtp.Send(email);
smtp.Disconnect(true);</code></pre>



<h2 class="wp-block-heading">Change Your SMTP Provider</h2>



<p>To change the above code to use a different email provider simply update the host parameter (the first parameter) passed to the <code>smtp.Connect()</code> method, for example:</p>



<pre class="wp-block-code"><code>// gmail
smtp.Connect("smtp.gmail.com", 587, SecureSocketOptions.StartTls);

// hotmail
smtp.Connect("smtp.live.com", 587, SecureSocketOptions.StartTls);

// office 365
smtp.Connect("smtp.office365.com", 587, SecureSocketOptions.StartTls);</code></pre>



<h2 class="wp-block-heading">Wrapping it up in an Email Service</h2>



<p>To encapsulate the email sending functionality and make it easy to send email from anywhere in your ASP.NET Core application you can create an <code>EmailService</code> class and <code>IEmailService</code> interface like below.</p>



<pre class="wp-block-code"><code>using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Options;
using MimeKit;
using MimeKit.Text;
using WebApi.Helpers;

namespace WebApi.Services
{
    public interface IEmailService
    {
        void Send(string from, string to, string subject, string html);
    }

    public class EmailService : IEmailService
    {
        private readonly AppSettings _appSettings;

        public EmailService(IOptions&lt;AppSettings&gt; appSettings)
        {
            _appSettings = appSettings.Value;
        }

        public void Send(string from, string to, string subject, string html)
        {
            // create message
            var email = new MimeMessage();
            email.From.Add(MailboxAddress.Parse(from));
            email.To.Add(MailboxAddress.Parse(to));
            email.Subject = subject;
            email.Body = new TextPart(TextFormat.Html) { Text = html };

            // send email
            using var smtp = new SmtpClient();
            smtp.Connect(_appSettings.SmtpHost, _appSettings.SmtpPort, SecureSocketOptions.StartTls);
            smtp.Authenticate(_appSettings.SmtpUser, _appSettings.SmtpPass);
            smtp.Send(email);
            smtp.Disconnect(true);
        }
    }
}</code></pre>



<h2 class="wp-block-heading">Conclusion</h2>



<p>I hope above tutorial can help you if you encounter issue when send email via your Asp.net Core application. See you on next tips!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/using-mailkit-to-send-email-asp-net-core-3-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Detect Session Timeout and Redirect to Login Page in ASP.NET</title>
		<link>https://topreviewhostingasp.net/how-to-detect-session-timeout-and-redirect-to-login-page-in-asp-net/</link>
					<comments>https://topreviewhostingasp.net/how-to-detect-session-timeout-and-redirect-to-login-page-in-asp-net/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Thu, 10 Dec 2020 04:09:44 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp.net tips]]></category>
		<category><![CDATA[asp.net tutorial]]></category>
		<category><![CDATA[detect session asp net]]></category>
		<category><![CDATA[session asp net]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2821</guid>

					<description><![CDATA[This is example of&#160;Detecting Session Timeout and Redirect to Login Page in ASP.NET, session timeout occurs when user is idle for the time specified as in web.config file. 1st Method In web.config file, set the sessionstate mode to inproc and authentication mode to Forms I&#8217;ve created three pages in this example , one is login [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>This is example of&nbsp;Detecting Session Timeout and Redirect to Login Page in ASP.NET, session timeout occurs when user is idle for the time specified as in web.config file.</p>



<p><strong>1st Method</strong></p>



<p>In web.config file, set the sessionstate mode to inproc and authentication mode to Forms</p>



<pre class="wp-block-code"><code>&lt;system.web>
&lt;compilation debug="true"/>
&lt;authentication mode="Forms"/>
&lt;sessionState mode="InProc" cookieless="false" timeout="1">
&lt;/sessionState>
&lt;/system.web> </code></pre>



<p>I&#8217;ve created three pages in this example , one is login page , when session expires , I redirect to this page , one is navigation page where I&#8217;ll check if session is valid or not , if it is valid than only user will see this page other wise he gets redirected to login page.</p>



<p><strong>Add Global.asax class file in root of your application or website.<br>This method works only if Global.asax is present in application.</strong></p>



<p>Write below mentioned code in Page_Init event of the page where we want to check for session timeout.</p>



<p>we can also put this code in in a class and inherit all pages of application from this class acting as base class for all pages to check for session timeout.</p>



<p><strong>C# CODE</strong></p>



<pre class="wp-block-code"><code>protected void Page_Init(object sender, EventArgs e)
    {
        if (Context.Session != null)
        {
            if (Session.IsNewSession)
            {
                HttpCookie newSessionIdCookie = Request.Cookies&#91;"ASP.NET_SessionId"];
                if (newSessionIdCookie != null)
                {
                    string newSessionIdCookieValue = newSessionIdCookie.Value;
                    if (newSessionIdCookieValue != string.Empty)
                    {
                        // This means Session was timed Out and New Session was started
                        Response.Redirect("Login.aspx");
                    }
                }
            }
        }
    }</code></pre>



<p><strong>VB.NET</strong></p>



<pre class="wp-block-code"><code>Protected Sub Page_Init(sender As Object, e As EventArgs)
 If Context.Session IsNot Nothing Then
  If Session.IsNewSession Then
   Dim newSessionIdCookie As HttpCookie = Request.Cookies("ASP.NET_SessionId")
   If newSessionIdCookie IsNot Nothing Then
    Dim newSessionIdCookieValue As String = newSessionIdCookie.Value
    If newSessionIdCookieValue &lt;> String.Empty Then
     ' This means Session was timed Out and New Session was started
     Response.Redirect("Login.aspx")
    End If
   End If
  End If
 End If
End Sub</code></pre>



<p><strong>2nd Method.</strong></p>



<p><strong>Code for Default.aspx</strong></p>



<pre class="wp-block-code"><code>&lt;%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>

&lt;!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

&lt;html xmlns="http://www.w3.org/1999/xhtml" >
&lt;head runat="server">
&lt;title>Untitled Page&lt;/title>
&lt;/head>
&lt;body>
&lt;form id="form1" runat="server">
&lt;div>
&lt;asp:Button ID="btnSessionStart"
runat="server"
OnClick="btnSessionStart_Click"
Text="Start Session" />&lt;br />
&lt;br />
&lt;br />
&lt;asp:Button ID="btnCheck"
runat="server"
OnClick="btnCheck_Click"
Text="Check Session ID" />
&lt;br />
&lt;asp:TextBox ID="txtSession"
runat="server"
Width="266px">
&lt;/asp:TextBox>&lt;br />
&lt;br />
&lt;asp:Button ID="btnGO"
runat="server"
OnClick="btnGO_Click"
Text="Go to Other Page" />
&lt;br />
&lt;br />
&lt;/div>
&lt;/form>
&lt;/body>
&lt;/html></code></pre>



<p>And the code behind for this page is like</p>



<pre class="wp-block-code"><code>protected void btnSessionStart_Click
(object sender, EventArgs e)
{
Guid Session_id = Guid.NewGuid();
Session&#91;"SessionID"]
= Session_id.ToString();

}
protected void btnCheck_Click
(object sender, EventArgs e)
{
if (Session&#91;"SessionID"] != null)
txtSession.Text =
Session&#91;"SessionID"].ToString();
else
txtSession.Text =
"Session has expired";
}
protected void btnGO_Click
(object sender, EventArgs e)
{
Response.Redirect("Default2.aspx");
}</code></pre>



<p><strong>On the page where we want to check the session has timed out or not, we need to check it in the Page_Init event of the page , if session is not null than user will be able to go to the page other wise he will be redirected to login page.</strong></p>



<pre class="wp-block-code"><code>&lt;html xmlns="http://www.w3.org/1999/xhtml" >
&lt;head runat="server">
&lt;title>Untitled Page&lt;/title>
&lt;/head>
&lt;body>
&lt;form id="form1" runat="server">
&lt;div>
&lt;asp:Button ID="btnHome"
runat="server" OnClick="btnHome_Click"
Text="Home" />&lt;/div>
&lt;/form>
&lt;/body>
&lt;/html></code></pre>



<p>And the Code behind for this page is</p>



<pre class="wp-block-code"><code>protected void Page_Init(object sender, EventArgs e)
{
CheckSession();
}
protected void btnHome_Click(object sender, EventArgs e)
{
Response.Redirect("Default.aspx");
}

private void CheckSession()
{
if (Session&#91;"SessionID"] == null)
{
Response.Redirect("Login.aspx");
}

}</code></pre>



<p>If we need to check this in all the pages of application than we can create a BaseClass and write the above mentioned code of CheckSession and Page_Init part and drive all ur pages from this class by typing BaseClassName in place of System.Web.UI.Page and it will check all pages for session timeout every time page is loaded</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-detect-session-timeout-and-redirect-to-login-page-in-asp-net/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Wiring up Ninject with ASP.NET Core 2.0</title>
		<link>https://topreviewhostingasp.net/how-to-wiring-up-ninject-with-asp-net-core-2-0/</link>
					<comments>https://topreviewhostingasp.net/how-to-wiring-up-ninject-with-asp-net-core-2-0/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 08 May 2018 07:25:35 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[ASP.NET Hosting]]></category>
		<category><![CDATA[asp.net tips]]></category>
		<category><![CDATA[asp.net tutorial]]></category>
		<category><![CDATA[ninject asp.net]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=1541</guid>

					<description><![CDATA[Ninject is a lightning-fast, ultra-lightweight dependency injector for .NET applications. It helps you split your application into a collection of loosely-coupled, highly-cohesive pieces, and then glue them back together in a flexible manner. By using Ninject to support your software&#8217;s architecture, your code will become easier to write, reuse, test, and modify. To test if the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="http://www.ninject.org/">Ninject</a> is a lightning-fast, ultra-lightweight dependency injector for .NET applications. It helps you split your application into a collection of loosely-coupled, highly-cohesive pieces, and then glue them back together in a flexible manner. By using Ninject to support your software&#8217;s architecture, your code will become easier to write, reuse, test, and modify.</p>
<p>To test if the injector is working correctly, create a service that implements an interface</p>
<pre class="lang:default decode:true ">    public interface ITestService
    {
        string GetData();
    }

    public class TestService : ITestService
    {
        public string GetData()
        {
            return "some magic string";
        }
    }</pre>
<h4>Download the package from Nuget</h4>
<p>Using the package manager console <code>Install-Package Ninject -Version 3.3.4</code></p>
<p>Using dotnet cli <code>dotnet add package Ninject --version 3.3.4</code></p>
<h4>Add these members to <code>Startup.cs</code> class as shown below</h4>
<pre class="lang:default decode:true ">    private readonly AsyncLocal&lt;Scope&gt; scopeProvider = new AsyncLocal&lt;Scope&gt;();
    private IKernel Kernel { get; set; }

    private object Resolve(Type type) =&gt; Kernel.Get(type);
    private object RequestScope(IContext context) =&gt; scopeProvider.Value;  

    private sealed class Scope : DisposableObject { }</pre>
<h4>Add the following binding in the end of <code>ConfigureServices</code> (<code>Startup.cs</code>)</h4>
<p><code>services.AddSingleton&lt;IHttpContextAccessor, HttpContextAccessor&gt;();</code></p>
<h4>Create class <code>RequestScopingStartupFilter</code> implementing the <code>IStartupFilter</code> interface</h4>
<pre class="lang:default decode:true ">    public sealed class RequestScopingStartupFilter : IStartupFilter
    {
        private readonly Func&lt;IDisposable&gt; requestScopeProvider;

        public RequestScopingStartupFilter(Func&lt;IDisposable&gt; requestScopeProvider)
        {
            if (requestScopeProvider == null)
            {
                throw new ArgumentNullException(nameof(requestScopeProvider));
            }

            this.requestScopeProvider = requestScopeProvider;
        }

        public Action&lt;IApplicationBuilder&gt; Configure(Action&lt;IApplicationBuilder&gt; nextFilter)
        {
            return builder =&gt;
            {
                ConfigureRequestScoping(builder);

                nextFilter(builder);
            };
        }

        private void ConfigureRequestScoping(IApplicationBuilder builder)
        {
            builder.Use(async (context, next) =&gt;
            {
                using (var scope = this.requestScopeProvider())
                {
                    await next();
                }
            });
        }
    }</pre>
<h4>Create a static class <code>AspNetCoreExtensions</code> with the following extension method</h4>
<pre class="lang:default decode:true ">    using System;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.DependencyInjection;

    public static class AspNetCoreExtensions
    {
        public static void AddRequestScopingMiddleware(this IServiceCollection services, 
            Func&lt;IDisposable&gt; requestScopeProvider)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (requestScopeProvider == null)
            {
                throw new ArgumentNullException(nameof(requestScopeProvider));
            }

            services
                .AddSingleton&lt;IStartupFilter&gt;(new
                    RequestScopingStartupFilter(requestScopeProvider));
        }
    }</pre>
<h4>Configure to use the middleware in <code>ConfigureServices</code>(in the end of the method)</h4>
<p><code>services.AddRequestScopingMiddleware(() =&gt; scopeProvider.Value = new Scope());</code></p>
<h4>Create a file <code>Activators.cs</code> with the following</h4>
<pre class="lang:default decode:true ">   public sealed class DelegatingControllerActivator : IControllerActivator
        {
            private readonly Func&lt;ControllerContext, object&gt; controllerCreator;
            private readonly Action&lt;ControllerContext, object&gt; controllerReleaser;

            public DelegatingControllerActivator(Func&lt;ControllerContext, object&gt; controllerCreator,
                Action&lt;ControllerContext, object&gt; controllerReleaser = null)
            {
                this.controllerCreator = controllerCreator ?? 
                    throw new ArgumentNullException(nameof(controllerCreator));
                this.controllerReleaser = controllerReleaser ?? ((_, __) =&gt; { });
            }

            public object Create(ControllerContext context) =&gt; this.controllerCreator(context);
            public void Release(ControllerContext context, object controller) =&gt;             
                this.controllerReleaser(context, controller);
        }</pre>
<h4>Add the following extension method to <code>AspNetCoreExtensions.cs</code></h4>
<pre class="lang:default decode:true ">        public static void AddCustomControllerActivation(this IServiceCollection services,
            Func&lt;Type, object&gt; activator)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            if (activator == null) throw new ArgumentNullException(nameof(activator));

            services.AddSingleton&lt;IControllerActivator&gt;(new DelegatingControllerActivator(
                context =&gt; activator(context.ActionDescriptor.ControllerTypeInfo.AsType())));
        }</pre>
<h4>Append the following to the end of <code>ConfigureServices</code></h4>
<p><code>services.AddCustomControllerActivation(Resolve);</code></p>
<h4>Add another class to <code>Activators.cs</code></h4>
<pre class="lang:default decode:true ">        public sealed class DelegatingViewComponentActivator : IViewComponentActivator
        {
            private readonly Func&lt;Type, object&gt; viewComponentCreator;
            private readonly Action&lt;object&gt; viewComponentReleaser;

            public DelegatingViewComponentActivator(Func&lt;Type, object&gt; viewComponentCreator,
                Action&lt;object&gt; viewComponentReleaser = null)
            {
                this.viewComponentCreator = viewComponentCreator ?? 
                    throw new ArgumentNullException(nameof(viewComponentCreator));
                this.viewComponentReleaser = viewComponentReleaser ?? (_ =&gt; { });
            }

            public object Create(ViewComponentContext context) =&gt;
                this.viewComponentCreator(context.ViewComponentDescriptor.TypeInfo.AsType());

            public void Release(ViewComponentContext context, object viewComponent) =&gt;
                this.viewComponentReleaser(viewComponent);
        }</pre>
<h4>And another extension method in <code>AspNetCoreExtensions.cs</code></h4>
<pre class="lang:default decode:true ">       public static void AddCustomViewComponentActivation(this IServiceCollection services, 
            Func&lt;Type, object&gt; activator)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            if (activator == null) throw new ArgumentNullException(nameof(activator));

            services.AddSingleton&lt;IViewComponentActivator&gt;(
new DelegatingViewComponentActivator(activator));
        }</pre>
<p>then call it form <code>ConfigureServices</code> (should be the last invoked)</p>
<p>This is what <code>ConfigureServices</code> should look like now</p>
<pre class="lang:default decode:true ">        public void ConfigureServices(IServiceCollection services)
        {
            // Other configurations

            services.AddSingleton&lt;IHttpContextAccessor, HttpContextAccessor&gt;();

            services.AddRequestScopingMiddleware(() =&gt; scopeProvider.Value = new Scope());
            services.AddCustomControllerActivation(Resolve);
            services.AddCustomViewComponentActivation(Resolve);

        }</pre>
<h4>Create an <code>ApplicationBuilderExtensions.cs</code> with a static class in it</h4>
<pre class="lang:default decode:true ">    using System;
    using System.Globalization;
    using System.Linq;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc.ApplicationParts;
    using Microsoft.AspNetCore.Mvc.Controllers;
    using Microsoft.Extensions.DependencyInjection;
    using Ninject;

    public static class ApplicationBuilderExtensions
    {
        public static void BindToMethod&lt;T&gt;(this IKernel config, Func&lt;T&gt; method)
 =&gt; config.Bind&lt;T&gt;().ToMethod(c =&gt; method());

        public static Type[] GetControllerTypes(this IApplicationBuilder builder)
        {
            var manager = builder.ApplicationServices.GetRequiredService&lt;ApplicationPartManager&gt;();

            var feature = new ControllerFeature();
            manager.PopulateFeature(feature);

            return feature.Controllers.Select(t =&gt; t.AsType()).ToArray();
        }

        public static T GetRequestService&lt;T&gt;(this IApplicationBuilder builder) where T : class
        {
            if (builder == null) throw new ArgumentNullException(nameof(builder));

            return GetRequestServiceProvider(builder).GetService&lt;T&gt;();
        }

        private static IServiceProvider GetRequestServiceProvider(IApplicationBuilder builder)
        {
            var accessor = builder.ApplicationServices.GetService&lt;IHttpContextAccessor&gt;();

            if (accessor == null)
            {
                throw new InvalidOperationException(      
          typeof(IHttpContextAccessor).FullName);
            }

            var context = accessor.HttpContext;

            if (context == null)
            {
                throw new InvalidOperationException("No HttpContext.");
            }

            return context.RequestServices;
        }
    }</pre>
<p>Add the following method in <code>Startup</code> class</p>
<pre class="lang:default decode:true ">        private IKernel RegisterApplicationComponents(IApplicationBuilder app)
        {
            // IKernelConfiguration config = new KernelConfiguration();
            var kernel = new StandardKernel();

            // Register application services
            foreach (var ctrlType in app.GetControllerTypes())
            {
                kernel.Bind(ctrlType).ToSelf().InScope(RequestScope);
            }

            // This is where our bindings are configurated
             kernel.Bind&lt;ITestService&gt;().To&lt;TestService&gt;().InScope(RequestScope);            

            // Cross-wire required framework services
            kernel.BindToMethod(app.GetRequestService&lt;IViewBufferScope&gt;);

            return kernel;
        }</pre>
<p>and call it from <code>Configure</code> (in the beginning)</p>
<p><code>this.Kernel = this.RegisterApplicationComponents(app);</code></p>
<h4>Create a <code>TestController</code> to see if our DI works</h4>
<pre class="lang:default decode:true ">    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        private readonly ITestService testService;

        public ValuesController(ITestService testService)
        {
            this.testService = testService;
            this.factory = factory;
        }

        [HttpGet]
        public IActionResult Get()
        {
            var result = this.testService.GetData();

            return this.Ok(result);
        }
    }</pre>
<p>Place a breakpoint in the constructor of our <code>TestService</code> and in the <code>Get</code>action to see the magic.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-wiring-up-ninject-with-asp-net-core-2-0/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Automate Reload Configuration in ASP.NET Core</title>
		<link>https://topreviewhostingasp.net/automate-reload-configuration-asp-net-core/</link>
					<comments>https://topreviewhostingasp.net/automate-reload-configuration-asp-net-core/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 29 Aug 2017 04:16:48 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp.net core tips]]></category>
		<category><![CDATA[asp.net core tutorial]]></category>
		<category><![CDATA[asp.net tips]]></category>
		<category><![CDATA[asp.net tutorial]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=758</guid>

					<description><![CDATA[In this article, I want to explore IOptionsSnapshot and show how to work with IOptionsSnapshot in ASP.NET Core 1.1. We will use the dot-net CLI to create a new project and configure it using the reload technique in combination with IOptionsSnapshot. Make sure you are using at least ASP.NET Core 1.1. Get started by creating [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In this article, I want to explore IOptionsSnapshot and show how to work with IOptionsSnapshot in ASP.NET Core 1.1.</p>
<p>We will use the dot-net CLI to create a new project and configure it using the reload technique in combination with IOptionsSnapshot.</p>
<p>Make sure you are using at least ASP.NET Core 1.1. Get started by creating a new folder that you want to work in, opening a console there and typingdotnet new mvc and dotnet restore to get the project in a starting position. Then open up a console and type code. to start Visual Studio Code on the current level.</p>
<p>You should now see all the files and folders of your project. We can now go ahead and create a typed class which represents the configuration we want to work with. In this case, this is just a file with a name property.</p>
<pre class="lang:default decode:true  ">Config 
  └── myConfig.json 
  Controllers └── ... 
  Views └── ... 
  wwwroot └── ... ... 
  Program.cs 
  Startup.cs</pre>
<p>myConfig.json</p>
<pre class="lang:default decode:true">{
    "Person": {
        "Firstname": "John Doe"
    }
}</pre>
<p>This leads us to the class</p>
<pre class="lang:default decode:true">public class Person  
{
    public string Firstname { get; set; }
}</pre>
<pre class="lang:default decode:true">Config  
  └── myConfig.json  
  Controllers └── ...  
  Views └── ...  
  wwwroot └── ... ...  
  Program.cs  
  Startup.cs</pre>
<p>which represents our configuration in our application.</p>
<p>We have to modify our constructor of the Startup.cs file a bit to load this new file:</p>
<pre class="lang:default decode:true">public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddEnvironmentVariables();
    Configuration = builder.Build();
}</pre>
<p>This then becomes:</p>
<pre class="lang:default decode:true">public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddJsonFile($"config/myConfig.json", optional: false, reloadOnChange: true)
        .AddEnvironmentVariables();
    Configuration = builder.Build();
}</pre>
<p>Pay attention to the realoadOnChange: true because that is what we are reaching out for.</p>
<p>So now that we loaded the file we need to add it to our configuration which is used in our app. Let&#8217;s do this by adding the statement in the ConfigureServices-Method:</p>
<pre class="lang:default decode:true">public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.Configure&lt;Person&gt;(Configuration.GetSection("Person"));
}</pre>
<p>Here we are mapping our values in JSON to a typed class called “Person.”</p>
<p>Now, this configuration is available through dependency injection and we can use it in our controllers!</p>
<pre class="lang:default decode:true">public class HomeController : Controller  
{
    private readonly Person _person;
    public HomeController(IOptionsSnapshot&lt;Person&gt; person)
    {
        _person = person.Value;
    }
}</pre>
<p>Pay attention to the “IOptionsSnapshot” we injected here which is different from the previous ASP.NET Core versions. Be sure to have the &#8220;Microsoft.Extensions.Options&#8221;: &#8220;1.1.0&#8221; package installed and that you are using ASP.NET Core 1.1. We can now inject the IOptionsSnapshot&lt;T&gt; in our controller and use its value. For testing, we save the Firstname in the ViewData displaying it afterward.</p>
<pre class="lang:default decode:true">namespace WebApplication6.Controllers
{
    public class HomeController : Controller
    {
        private readonly Person _person;
        public HomeController(IOptionsSnapshot&lt;Person&gt; person)
        {
            _person = person.Value;
        }
        public IActionResult Index()
        {
            ViewData["FirstName"] = _person.Firstname;
            return View();
        }
    }
}</pre>
<p>Index.cshtml</p>
<pre class="lang:default decode:true">&lt;h3&gt;@(ViewData["FirstName"])&lt;/h3&gt;</pre>
<p>If you now start the web application via dotnet run and you change the configuration without restarting the application, hit F5 to refresh the browser and you will see the new values.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/automate-reload-configuration-asp-net-core/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>ASP.NET Core &#8211; How it Works?!</title>
		<link>https://topreviewhostingasp.net/asp-net-core-works/</link>
					<comments>https://topreviewhostingasp.net/asp-net-core-works/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Wed, 26 Apr 2017 04:46:35 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp.net core tips]]></category>
		<category><![CDATA[asp.net core tutorial]]></category>
		<category><![CDATA[asp.net core works how]]></category>
		<category><![CDATA[asp.net tips]]></category>
		<category><![CDATA[asp.net works]]></category>
		<category><![CDATA[kestrel asp.net core]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=570</guid>

					<description><![CDATA[The hosting model for ASP.NET Core is dramatically different from previous versions of ASP.NET. This is also one area where I’ve seen a fair amount of misunderstanding. ASP.NET Core is a set of libraries you can install into a project using the NuGet package manager. One of the packages you might install for HTTP message [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The hosting model for ASP.NET Core is dramatically different from previous versions of ASP.NET. This is also one area where I’ve seen a fair amount of misunderstanding.</p>
<p>ASP.NET Core is a set of libraries you can install into a project using the NuGet package manager. One of the packages you might install for HTTP message processing is a package named Microsoft.AspNetCore.Server.Kestrel. The word server is in the name because this new version of ASP.NET includes its own web servers, and the featured server has the name Kestrel.</p>
<p>In the animal kingdom, a Kestrel is a bird of prey in the falcon family, but in the world of ASP.NET, Kestrel is a cross-platform web server. Kestrel builds on top of <a href="https://github.com/libuv/libuv">libuv</a>, a cross-platform library for asynchronous I/O. libuv gives Kestrel a consistent streaming API to use across Windows and Linux. You also have the option of plugging in a server based on the Windows HTTP Server API (Web Listener), or writing your own IServer implementation. Without good reason, you’ll want to use Kestrel by default.</p>
<h1><strong>An Overview of How It Works</strong></h1>
<p>You can configure the server for your application in the entry point of the application. There is no Application_Start event in this new version of ASP.NET, nor is there any default XML configuration files. Instead, the start of the application is a static Main method, and configuration lives in the code.</p>
<pre class="lang:default decode:true">public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup&lt;Startup&gt;()
            .Build(); 

        host.Run();
    }
}</pre>
<p>If you are looking at the above Program class with a static Main method and thinking the code looks like what you would see in a .NET console mode application, then you are thinking correctly. Compiling an ASP.NET project still produces a .dll file, but with .NET Core we launch the web server from the command line with the dotnet command line interface. The dotnet host will ultimately call into the Main method. In this way of working, .NET Core resembles environments like Java, Ruby, and Python.</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-572" src="https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_1-2.png" alt="" width="804" height="457" srcset="https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_1-2.png 804w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_1-2-300x171.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_1-2-768x437.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_1-2-50x28.png 50w" sizes="(max-width: 804px) 100vw, 804px" /></p>
<p>If you are working on ASP.NET Core from Visual Studio, then you might never see the command line. Visual Studio continues to do a job it has always done, which is to hide some of the lower level details. With Visual Studio, you can set the application to run with Kestrel as a direct host, or to run the application in IIS Express (the default setting). In both cases, the dotnet host and Kestrel server are in play, even when using IIS Express. This brings us to the topic of running applications in production.</p>
<h2><strong>ASP.NET Core Applications in Production</strong></h2>
<p>One you realize that ASP.NET includes a cross-platform host and web server, you might think you have all the pieces you need to push to production. There is some truth to this line of thought. Once you’ve invoked the Run method on the WebHost object in the above code, you have a running web server that will listen to HTTP requests and can work on everything from a 32 core Linux server to a Raspberry Pi. However, Microsoft strongly suggests using a hardened reverse proxy in front of your Kestrel server in production. The proxy could be IIS on Windows, or Apache or NGINX.</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone wp-image-573" src="https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_2-1.png" alt="" width="708" height="369" srcset="https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_2-1.png 800w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_2-1-300x156.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_2-1-768x400.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_2-1-50x26.png 50w" sizes="(max-width: 708px) 100vw, 708px" /></p>
<p>Why the reverse proxy? In short because technologies like IIS and Apache have been around for over 20 years and have seen all the evils the Internet can deliver to a network socket. Kestrel, on the other hand, is still a newborn babe. Also, reliable servers require additional infrastructure like careful process management to restart failed applications. Outside of ASP.NET, in the world of Java, Python, Ruby, and NodeJS web apps, you’ll see tools like Phusion Passenger and PM2 work in combination with the reverse proxy. These types of tools provide the watchdog monitoring, logging, balancing, and overall process management needed for a robust server. With ASP.NET Core on Windows you can use IIS to achieve the same goals. HTTP requests will still arrive at IIS first, and IIS can forward requests to the Kestrel application. You can have multiple applications deployed behind a single instance of IIS, and IIS will manage the application and provide logging, request filtering, URL rewrites, and many other useful features. In a way, this isn’t much different than what we’ve done in the past with ASP.NET, but once you dig behind the architectural diagrams, you’ll see the details are very different.</p>
<h2><strong>What’s Different?</strong></h2>
<p>Deploying ASP.NET Core applications to IIS requires a web.config file. ASP.NET Core knows nothing about web.config files. The web.config file only exists to configure IIS in a reverse proxy role. A typical web.config file will look like the following.</p>
<pre class="lang:default decode:true">&lt;configuration&gt;
  &lt;system.webServer&gt;
    &lt;handlers&gt;
      &lt;add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" /&gt;
    &lt;/handlers&gt;
    &lt;aspNetCore processPath="dotnet" arguments=".\TheWebApp.dll" stdoutLogEnabled="false"
                   stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" /&gt;
  &lt;/system.webServer&gt;
&lt;/configuration&gt;</pre>
<p>The web.config file instructs IIS to send requests for all paths and verbs to a new HTTP handler named aspNetCore. This ASP.NET Core Module for IIS is a piece of software you’ll need to install on an IIS server to run ASP.NET Core applications. The ASP.NET Core Module is available with the .NET Core SDK install, or with a special <a href="https://topreviewhostingasp.net/best-asp-net-hosting-awards-2017/">Windows Server Hosting</a> .NET Core installer.</p>
<p>The second bit of the web.config file configures the ASP.NET Core module with instructions on how to start your application, which is to use the same dotnet command we saw earlier. Now, instead of our ASP.NET application running inside of a w3wp.exe IIS worker process, the application will execute inside of a dotnet.exe process.</p>
<p>With a better idea of how ASP.NET Core runs in production, let’s talk about benefits and risks.</p>
<h2><strong>Benefits</strong></h2>
<p>One benefit to Kestrel is the ability to execute across different platforms. You can author an ASP.NET application on Windows using Visual Studio and IIS Express, but deploy the application on Linux with Apache in front. In all scenarios, the server is always Kestrel and your application code doesn’t need to change.</p>
<p>Another benefit to Kestrel is the incredible work Microsoft has put into making a blazing fast web server with managed code. Inside the readme file for the <a href="https://github.com/aspnet/benchmarks">ASP.NET Benchmarks repository</a>, you’ll currently find benchmarks showing ASP.NET Core serving five times the number of requests per second as ASP.NET 4.6 on the same hardware. 313,001 requests per second compared to 57, 843.</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-574" src="https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_3.png" alt="" width="804" height="604" srcset="https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_3.png 804w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_3-300x225.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_3-768x577.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_3-50x38.png 50w" sizes="(max-width: 804px) 100vw, 804px" /></p>
<p>Of course, benchmark code and benchmark results don’t always reflect how a specific business application will behave. It’s like seeing an F1 racing car manufactured by Toyota on the television and then thinking you’ll find a car that goes 220 mph at the local Toyota dealer. What you will find at the dealer are cars that indirectly benefit from the millions of dollars that Toyota puts into researching new technologies for their F1 cars. The benefits trickle down.</p>
<p>I decided to try some comparative benchmarks of my own. I created three applications with ASP.NET WebForms, ASP.NET MVC 5, and ASP.NET MVC Core. Each application delivers 3kb of HTML to the client using the typical patterns you would find in business applications. For example, using a master page in WebForms and using a Layout page in MVC. For ASP.NET MVC Core, I ran tests against a naked Kestrel server as well as a Kestrel server proxied by IIS.</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone wp-image-575" src="https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_4.png" alt="" width="586" height="388" srcset="https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_4.png 800w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_4-300x199.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_4-768x509.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_4-50x33.png 50w" sizes="(max-width: 586px) 100vw, 586px" /></p>
<p>In my tests, the naked Kestrel server delivered 5 times the throughput of WebForms, and over twice the throughput of MVC 5. Once I moved the Core application behind IIS however, throughput dropped below the level of MVC 5. I know these results might surprise many people who believe that ASP.NET Core is inherently faster and lighter than its predecessors. However, ASP.NET Core’s predecessors were deeply integrated into IIS and could execute inside the same worker process where sockets were open. The current recommended setup adds an additional hop.</p>
<p>Another surprise – switching the ASP.NET Core application to run on the full .NET framework instead of .NET Core resulted in very little change in the throughput numbers. As developers, we want to believe .NET Core is also inherently faster and lighter than the full .NET framework, but for runtime performance in this specific application, the difference appears to be negligible.</p>
<p>I do think we can reasonably expect the performance of ASP.NET Core with IIS to improve in the future, so we’ll leave performance as a benefit.</p>
<h2><strong>Risks</strong></h2>
<p>The biggest risk I’ve seen in the new hosting model is the confusion that results in using IIS with ASP.NET Core. There are ASP.NET related settings in IIS that have no impact on a .NET Core application. These are settings like the pipeline mode (integrated or classic), and the setting to select a version of the .NET framework for a specific AppPool.</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-576" src="https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_5.png" alt="" width="804" height="444" srcset="https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_5.png 804w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_5-300x166.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_5-768x424.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/image_5-50x28.png 50w" sizes="(max-width: 804px) 100vw, 804px" /></p>
<p>Developers and IT operations will need to understand the new deployment strategy and understand which IIS settings are significant and which settings to ignore. Both parties will also need to learn new troubleshooting techniques and diagnose a new set of common errors. 502.5 – “Failed to start process” is a terrifying new common error. One reason for this error is that the web.config file specifies incorrect arguments for the dotnet host.</p>
<h2><strong>Summary</strong></h2>
<p>Currently, I feel the hosting area is one of the bigger areas of risk in ASP.NET Core. However, I think we will be able to mitigate the risks over time through a combination of experience, education, experimentation, and improvements from Microsoft based on customer feedback. It is important for developers and IT operations to look at how to host an ASP.NET core application early and not treat deployment as a known procedure that can wait till the end of the project.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/asp-net-core-works/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
