<?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 core tutorial &#8211; ASP.NET Hosting Reviews and Guides</title>
	<atom:link href="https://topreviewhostingasp.net/tag/asp-net-core-tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>https://topreviewhostingasp.net</link>
	<description>ASP.NET Hosting &#124; Reviews &#124; Tips &#38; Tutorial</description>
	<lastBuildDate>Tue, 23 Feb 2021 03:17:46 +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 core tutorial &#8211; ASP.NET Hosting Reviews and Guides</title>
	<link>https://topreviewhostingasp.net</link>
	<width>32</width>
	<height>32</height>
</image> 
	<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>Caching Static Resources Forever with ASP.NET Core</title>
		<link>https://topreviewhostingasp.net/caching-static-resources-forever-with-asp-net-core/</link>
					<comments>https://topreviewhostingasp.net/caching-static-resources-forever-with-asp-net-core/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Thu, 18 Feb 2021 04:11:12 +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[caching asp net core]]></category>
		<category><![CDATA[net core]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2924</guid>

					<description><![CDATA[Caching static resources like stylesheet, JavaScript, or image files allows improving the performance of your website. On the client-side, a static file will always be loaded from the cache which reduces the number of requests to the server and so, the time to get the page and its resources. On the server-side, as they are [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Caching static resources like stylesheet, JavaScript, or image files allows improving the performance of your website. On the client-side, a static file will always be loaded from the cache which reduces the number of requests to the server and so, the time to get the page and its resources. On the server-side, as they are fewer requests, the server can handle more clients without upgrading the hardware.</p>



<p>While caching is a great thing, you must ensure the client is always running the latest version of the application. I mean, when you deploy the next version of the website, you don&#8217;t want the client to use an obsolete cached version of a file.</p>



<h2 class="wp-block-heading">Versioned URL (Cache buster)</h2>



<p>To ensure the user always uses the latest version of a file, we must have a unique URL per version of a file. There are many strategies:</p>



<ul>
<li>Use the query string: <code>https://sample.com/file.js?v=123</code></li>
<li>Rename the file: <code>https://sample.com/file.123.js</code></li>
<li>Create a directory: <code>https://sample.com/123/file.js</code></li>
</ul>



<p>ASP.NET Core provides a mechanism using a <code>TagHelper</code> to append the version with the query string. It supports the most common HTML tags that target a static resource: <code>script</code>, <code>link</code> and <code>img</code>. All you have to do is append <code>asp-append-version="true"</code> to the tag:</p>



<pre class="wp-block-code"><code>&lt;link rel="stylesheet" href="~/css/site.css" asp-append-version="true" /&gt;
&lt;script src="~/js/site.js" asp-append-version="true"&gt;&lt;/script&gt;
&lt;img src="~/images/banner1.svg" asp-append-version="true" /&gt;</code></pre>



<p>This will produce:</p>



<pre class="wp-block-code"><code>&lt;link rel="stylesheet" href="/css/site.css?v=1wp5zz4e-mOPFx4X2O8seW_DmUtePn5xFJk1vB7JKRc" /&gt;
&lt;script src="/js/site.js?v=EWaMeWsJBYWmL2g_KkgXZQ5nPe-a3Ichp0LEgzXczKo"&gt;&lt;/script&gt;
&lt;img src="/images/banner1.svg?v=GaE_EmkeBf-yBbrJ26lpkGd4jkOSh1eVKJaNOw9I4uk" /&gt;</code></pre>



<p>The version is the SHA256 of the file encoded in base64. Of course, the hash is computed only once per file and stored in an <code>IMemoryCache</code>.</p>



<p>The URL of files are now unique and will change when the file change, so we can add a cache header to the response to indicate the client that the file can be stored in cache forever.</p>



<h2 class="wp-block-heading">Response headers</h2>



<p>To indicate the browser to store the file in its cache, we must send the <code>Cache-control</code> header and the <code>Expires</code> header for <code>HTTP/1.0</code> compatibility. To add these headers, we use the <code>OnPrepareResponse</code> callback of the <code>StaticFilesOptions</code>. Let&#8217;s modify the <code>Startup.cs</code> file:</p>



<pre class="wp-block-code"><code>public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseStaticFiles(new StaticFileOptions
    {
        OnPrepareResponse = context =&gt;
        {
            // Cache static file for 1 year
            if (!string.IsNullOrEmpty(context.Context.Request.Query["v"]))
            {
                context.Context.Response.Headers.Add("cache-control", new[] { "public,max-age=31536000" });
                context.Context.Response.Headers.Add("Expires", new[] { DateTime.UtcNow.AddYears(1).ToString("R") }); // Format RFC1123
            }
        }
    });

    app.UseMvc(routes =&gt;
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}</code></pre>



<p>You can check the headers are sent by using the Developer Console:</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="773" height="275" class="wp-image-2925" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/developerconsole.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/developerconsole.png 773w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/developerconsole-300x107.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/developerconsole-768x273.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/developerconsole-50x18.png 50w" sizes="(max-width: 773px) 100vw, 773px" /></figure>



<h2 class="wp-block-heading" id="conclusion-60e67e">Conclusion</h2>



<p>Using HTTP caching is important for performance reasons (client and server sides). With ASP.NET Core, you can take advantage of the provided <code>TagHelper</code>s to generate a versioned URL, and change the default configuration of the <code>StaticFilesMiddleware</code> to add the <code>Cache-control</code> header for these URLs.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/caching-static-resources-forever-with-asp-net-core/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Run MySQL Connector in ASP.NET Core</title>
		<link>https://topreviewhostingasp.net/how-to-run-mysql-connector-in-asp-net-core/</link>
					<comments>https://topreviewhostingasp.net/how-to-run-mysql-connector-in-asp-net-core/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Thu, 11 Feb 2021 03:49:22 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net core mysql]]></category>
		<category><![CDATA[asp.net core]]></category>
		<category><![CDATA[asp.net core tutorial]]></category>
		<category><![CDATA[mysql connector]]></category>
		<category><![CDATA[mysql connector tips]]></category>
		<category><![CDATA[mysql connector tutorial]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2907</guid>

					<description><![CDATA[This tutorial shows how to use MySQL database with MySQL Connector in Asp.net Core. Before we start it, please make sure you have installed MySQL 5.7, .NET Core, Visual Studio, and also Sakila sample database. Let&#8217;s Get Started 1. The first step is to create ASP.NET Core Web Application and you can name it. For [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>This tutorial shows how to use MySQL database with MySQL Connector in Asp.net Core.</p>



<p>Before we start it, please make sure you have installed MySQL 5.7, <a href="https://dotnet.microsoft.com/download" target="_blank" rel="noreferrer noopener">.NET Core</a>, Visual Studio, and also <a href="https://dev.mysql.com/doc/sakila/en/sakila-installation.html" target="_blank" rel="noreferrer noopener">Sakila sample database</a>.</p>



<h2 class="wp-block-heading">Let&#8217;s Get Started</h2>



<p>1. The first step is to create ASP.NET Core Web Application and you can name it. For example, we use MvcSakilaCore.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="955" height="582" class="wp-image-2908" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_010.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_010.png 955w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_010-300x183.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_010-768x468.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_010-50x30.png 50w" sizes="(max-width: 955px) 100vw, 955px" /></figure>



<p>2. Select Web Application template and No Authentication.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="800" height="620" class="wp-image-2909" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_020.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_020.png 800w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_020-300x233.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_020-768x595.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_020-50x39.png 50w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p>3. You will see the project below:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="768" height="416" class="wp-image-2910" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_030-768x416-1.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_030-768x416-1.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_030-768x416-1-300x163.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_030-768x416-1-50x27.png 50w" sizes="(max-width: 768px) 100vw, 768px" /></figure>



<p>4. Press F5 to run the application:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="768" height="409" class="wp-image-2911" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_040-768x409-1.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_040-768x409-1.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_040-768x409-1-300x160.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_040-768x409-1-50x27.png 50w" sizes="(max-width: 768px) 100vw, 768px" /></figure>



<p>5. Create a new folder named &#8220;Models&#8221; where it will store the database access:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="768" height="416" class="wp-image-2912" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_030-768x416-2.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_030-768x416-2.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_030-768x416-2-300x163.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_030-768x416-2-50x27.png 50w" sizes="(max-width: 768px) 100vw, 768px" /></figure>



<p>6. Installing MySQL Connector/NET Core Package</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="768" height="447" class="wp-image-2913" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/nuget-install.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/nuget-install.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/nuget-install-300x175.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/nuget-install-50x29.png 50w" sizes="(max-width: 768px) 100vw, 768px" /></figure>



<p>7. Add Connection string like below</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="678" height="98" class="wp-image-2914" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/connection-string.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/connection-string.png 678w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/connection-string-300x43.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/connection-string-50x7.png 50w" sizes="(max-width: 678px) 100vw, 678px" /></figure>



<p>8. Adding data modal classes.</p>



<p>For this example a Film class will be used. It contains the database fields as properties we want to show in our application.</p>



<pre class="wp-block-code"><code>using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MvcSakilaCore.Models
{
  public class Film
  {
    private SakilaContext context;

    public int FilmId { get; set; }

    public string Title { get; set; }

    public string Description { get; set; }

    public int ReleaseYear { get; set; }

    public int Length { get; set; }

    public string Rating { get; set; }
  }
}</code></pre>



<p>Create a new SakilaContext class that will contains the connections and Sakila database entities:</p>



<pre class="wp-block-code"><code>using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace MvcSakilaCore.Models
{
  public class SakilaContext
  {
    public string ConnectionString { get; set; }

    public SakilaContext(string connectionString)
    {
      this.ConnectionString = connectionString;
    }

    private MySqlConnection GetConnection()
    {
      return new MySqlConnection(ConnectionString);
    }

    public List&lt;Film&gt; GetAllFilms()
    {
      List&lt;Film&gt; list = new List&lt;Film&gt;();

      using (MySqlConnection conn = GetConnection())
      {
        conn.Open();
        MySqlCommand cmd = new MySqlCommand("SELECT * FROM film", conn);
        using (MySqlDataReader reader = cmd.ExecuteReader())
        {
          while (reader.Read())
          {
            list.Add(new Film()
            {
              FilmId = reader.GetInt32("film_id"),
              Title = reader.GetString("title"),
              Description = reader.GetString("description"),
              ReleaseYear = reader.GetInt32("release_year"),
              Length = reader.GetInt32("length"),
              Rating = reader.GetString("rating")
            });
          }
        }
      }

      return list;
    }
  }
}</code></pre>



<p>In order to be able to use our SakilaContext it’s required to register the instance as a service in our application. To do this add the code line in the Startup.cs file:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="998" height="630" class="wp-image-2915" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_3.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_3.png 998w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_3-300x189.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_3-768x485.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_3-50x32.png 50w" sizes="(max-width: 998px) 100vw, 998px" /></figure>



<p>9. Adding Film Controller</p>



<p>In Solution Explorer, right-click Controllers &gt; Add &gt; New Item… &gt; MVC Controller Class. Name the controller <strong>FilmsController</strong>:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="955" height="582" class="wp-image-2916" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-controller.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-controller.png 955w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-controller-300x183.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-controller-768x468.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-controller-50x30.png 50w" sizes="(max-width: 955px) 100vw, 955px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="768" height="416" class="wp-image-2917" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-controller-2.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-controller-2.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-controller-2-300x163.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-controller-2-50x27.png 50w" sizes="(max-width: 768px) 100vw, 768px" /></figure>



<p>Change the FilmsController code to this:</p>



<pre class="wp-block-code"><code>using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using MvcSakilaCore.Models;

// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860

namespace MvcSakilaCore.Controllers
{
  public class FilmsController : Controller
  {
    // GET: /&lt;controller&gt;/
    public IActionResult Index()
    {
      SakilaContext context = HttpContext.RequestServices.GetService(typeof(MvcSakilaCore.Models.SakilaContext)) as SakilaContext;

      return View(context.GetAllFilms());
    }
  }
}</code></pre>



<p>10. Creating the Films View</p>



<p>Start creating the Films folder under Views:</p>



<p>In Solution Explorer, right click Views &gt; Films &gt; Add &gt; New Item… &gt; ASP.NET &gt; MVC View Page</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="955" height="582" class="wp-image-2918" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-view.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-view.png 955w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-view-300x183.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-view-768x468.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/film-view-50x30.png 50w" sizes="(max-width: 955px) 100vw, 955px" /></figure>



<p>Add the following code into the new Index.cshtml view file:</p>



<pre class="wp-block-code"><code>@model IEnumerable&lt;MvcSakilaCore.Models.Film&gt;
@{
  ViewBag.Title = "Films";
}
&lt;h2&gt;Films&lt;/h2&gt;
&lt;table class="table"&gt;
  &lt;tr&gt;
    &lt;th&gt;Film ID&lt;/th&gt;
    &lt;th&gt;Title&lt;/th&gt;
    &lt;th&gt;Description&lt;/th&gt;
    &lt;th&gt;Release Year&lt;/th&gt;
    &lt;th&gt;Length&lt;/th&gt;
    &lt;th&gt;Rating&lt;/th&gt;
  &lt;/tr&gt;
  @foreach (var item in Model)
  {
    &lt;tr&gt;
      &lt;td&gt;
        @Html.DisplayFor(modelItem =&gt; item.FilmId)
      &lt;/td&gt;
      &lt;td&gt;
        @Html.DisplayFor(modelItem =&gt; item.Title)
      &lt;/td&gt;
      &lt;td&gt;
        @Html.DisplayFor(modelItem =&gt; item.Description)
      &lt;/td&gt;
      &lt;td&gt;
        @Html.DisplayFor(modelItem =&gt; item.ReleaseYear)
      &lt;/td&gt;
      &lt;td&gt;
        @Html.DisplayFor(modelItem =&gt; item.Length)
      &lt;/td&gt;
      &lt;td&gt;
        @Html.DisplayFor(modelItem =&gt; item.Rating)
      &lt;/td&gt;
    &lt;/tr&gt;
  }
&lt;/table&gt;</code></pre>



<p>Before run the application, add the Films path to the running url.</p>



<p>In Solution Explorer, right click MvcSakilaCore &gt; Properties &gt; Debug &gt; Launch URL &gt; Films:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="998" height="630" class="wp-image-2919" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_4.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_4.png 998w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_4-300x189.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_4-768x485.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_4-50x32.png 50w" sizes="(max-width: 998px) 100vw, 998px" /></figure>



<p>Run the application (press F5) and the Films list should be displayed:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="768" height="373" class="wp-image-2920" src="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_5.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_5.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_5-300x146.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2021/02/cnet_aspnetcore_5-50x24.png 50w" sizes="(max-width: 768px) 100vw, 768px" /></figure>



<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-run-mysql-connector-in-asp-net-core/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Redirect WWW and non-HTTPS in ASP.NET Core</title>
		<link>https://topreviewhostingasp.net/how-to-redirect-www-and-non-https-in-asp-net-core/</link>
					<comments>https://topreviewhostingasp.net/how-to-redirect-www-and-non-https-in-asp-net-core/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 12 Jan 2021 03:19:07 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net core url redirect]]></category>
		<category><![CDATA[asp.net core tips]]></category>
		<category><![CDATA[asp.net core tutorial]]></category>
		<category><![CDATA[redirect www website]]></category>
		<category><![CDATA[url redirect]]></category>
		<category><![CDATA[url redirect tips]]></category>
		<category><![CDATA[url redirect tutorial]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2843</guid>

					<description><![CDATA[In this article, we will give short tutorial about how to redirect your www and non-HTTPS ASP.NET Core website. This is to make sure that your site will be ranked higher, since Google does not like different URLs, for example ones with and without &#8220;www.&#8221; to show the same content. Redirect Request in ASP.NET Core [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>In this article, we will give short tutorial about how to redirect your www and non-HTTPS ASP.NET Core website. This is to make sure that your site will be ranked higher, since Google does not like different URLs, for example ones with and without &#8220;www.&#8221; to show the same content.</p>



<h2 class="wp-block-heading">Redirect Request in ASP.NET Core</h2>



<p>Please kindly install <a href="https://www.nuget.org/packages/Microsoft.AspNetCore.Rewrite/">Microsoft.AspNetCore.Rewrite package from NuGet</a>. Once you have installed it, you can redirect request. Just go to ASP.NET Core project, there is a &#8220;Configure&#8221; method, by adding rewrite rules to your application, it is possible to do redirect request.</p>



<h2 class="wp-block-heading">Redirect Non-HTTPS Request</h2>



<p>Please find &#8220;Configure&#8221; method in the Startup.cs file and edit it to contain the redirect you want. Note that you could put in conditional logic to only run this on a production environment.</p>



<pre class="wp-block-preformatted">  public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  {
            var options = new RewriteOptions();
            options.AddRedirectToHttps(301);
            app.UseRewriter(options);
  }</pre>



<p>The library also includes a &#8220;AddRedirectToHttpsPermanent&#8221; method if you want to use that. &#8220;AddRedirectToHttps&#8221; allows you to specify the status code explictly. For SSL certificate, provider like ASPHostPortal has support <a href="https://www.asphostportal.com/Lets-Encrypt-Hosting">Let&#8217;s Encrypt SSL</a> and you can install it directly via their control panel. They also offer paid SSL certificate from $48/year.</p>



<h2 class="wp-block-heading">Redirect WWW Request</h2>



<p>There is no built in method to redirect &#8220;www.&#8221; requests so this requires writing a custom class which can be used with the rewrite options, the class implements the &#8220;IRule&#8221; interface. Create the following class somewhere in the web project:</p>



<pre class="wp-block-preformatted">    public class NonWwwRule : IRule
    {
        public void ApplyRule(RewriteContext context)
        {
            var req = context.HttpContext.Request;
            var currentHost = req.Host;
            if (currentHost.Host.StartsWith("www."))
            {
                var newHost = new HostString(currentHost.Host.Substring(4), currentHost.Port ?? 80);
                var newUrl = new StringBuilder().Append("http://").Append(newHost).Append(req.PathBase).Append(req.Path).Append(req.QueryString);
                context.HttpContext.Response.Redirect(newUrl.ToString(), true);
                context.Result = RuleResult.EndResponse;
            }
        }
    }</pre>



<p>Note that it&#8217;s the second parameter in &#8220;Response.Redirect&#8221; which is responsible for setting &#8220;permanent&#8221; to &#8220;true&#8221;. This is what is responsible for the 301 redirect. In this example, the redirect goes to the HTTP version, not the HTTPS version, you can easily edit that if you want to save on another redirect.</p>



<p>Once the class is in your project, add the rule to the options (add before calling &#8220;UseRewriter&#8221;):</p>



<pre class="wp-block-preformatted">  public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  {
            var options = new RewriteOptions();
            options.Rules.Add(new NonWwwRule())
            app.UseRewriter(options);
  }</pre>



<p>By using this class as a new rule, a permanent redirect takes place for &#8220;www.&#8221; traffic to the non-WWW version. If you needed to, you could reverse the logic and redirect non-WWW to the &#8220;www.&#8221; version by editing the class.</p>



<h2 class="wp-block-heading">Summary</h2>



<p>I hope that article really helpful for you and above code can be applied on your ASP.NET Core project.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-redirect-www-and-non-https-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>Use Serilog ASP.NET Core to SQL Server Database</title>
		<link>https://topreviewhostingasp.net/use-serilog-asp-net-core-to-sql-server-database/</link>
					<comments>https://topreviewhostingasp.net/use-serilog-asp-net-core-to-sql-server-database/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Thu, 03 Dec 2020 04:03:24 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp.net core hosting]]></category>
		<category><![CDATA[asp.net core tips]]></category>
		<category><![CDATA[asp.net core tutorial]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[serilog asp net core]]></category>
		<category><![CDATA[sql server]]></category>
		<category><![CDATA[web host asp net core]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2813</guid>

					<description><![CDATA[Logging is an essential feature for any application, as it is necessary for detecting, investigating, and debugging issues. Serilog is a third-party, open source library that allows .NET developers to log structured data to the console, to files, and to several other kinds of data stores.  This article discusses how we can use Serilog to log structured [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Logging is an essential feature for any application, as it is necessary for detecting, investigating, and debugging issues. <a href="https://serilog.net/">Serilog</a> is a third-party, open source library that allows .NET developers to log structured data to the console, to files, and to several other kinds of data stores. </p>



<p>This article discusses how we can use Serilog to log structured data to a SQL Server database. To work with the code examples provided in this article, you should have Visual Studio 2019 installed in your system.</p>



<h2 class="wp-block-heading">Create Your First ASP.NET Core 3.0 Project</h2>



<p>Make sure you create your ASP.NET Core project in Visual Studio. We assume that you have installed Visual Studio on your computer.</p>



<h2 class="wp-block-heading">Install the NuGet packages for Serilog</h2>



<p>To work with Serilog, you should install the Serilog packages from NuGet. You can do this either via the NuGet package manager inside the Visual Studio 2019 IDE, or by executing the following commands at the NuGet package manager console:</p>



<pre class="wp-block-code"><code>Install-Package Serilog
Install-Package Serilog.AspNetCore
Install-Package Serilog.Sinks.MSSqlServer
Install-Package Serilog.Settings.Configuration</code></pre>



<h2 class="wp-block-heading">Initialize Serilog in Program.cs in ASP.NET Core</h2>



<p>The following code snippet illustrates how you can plug Serilog into ASP.NET Core. Note how the UseSerilog() extension method has been used to set Serilog as the logging provider.</p>



<pre class="wp-block-code"><code>public static IWebHost BuildWebHost(string[] args) =&gt;
            WebHost.CreateDefaultBuilder(args)
                   .UseStartup&lt;Startup&gt;()
                   .UseSerilog()
                   .Build();</code></pre>



<h2 class="wp-block-heading">Build an example web host in ASP.NET Core</h2>



<p>Naturally, we’ll need an application to illustrate the use of Serilog. Here is the complete source code of the Program class for our example app. Note how we’ve configured and built the web host.</p>



<pre class="wp-block-code"><code>    public class Program
    {
        public static void Main(string[] args)
        {
            IConfigurationRoot configuration = new
            ConfigurationBuilder().AddJsonFile("appsettings.json",
            optional: false, reloadOnChange: true).Build();
            Log.Logger = new LoggerConfiguration().ReadFrom.Configuration
            (configuration).CreateLogger();
            BuildWebHost(args).Run();
        }
        public static IWebHost BuildWebHost(string[] args) =&gt;
            WebHost.CreateDefaultBuilder(args)
                .UseStartup&lt;Startup&gt;()
                .UseSerilog()
                .Build();
    }</code></pre>



<h2 class="wp-block-heading">Configure database connection settings in ASP.NET Core</h2>



<p>When you create a new ASP.NET Core project in Visual Studio, the appsettings.json file is created by default. Here is where you can specify the database connection string and other configuration information. Open the appsettings.json file from the project we created earlier and enter the following information:</p>



<pre class="wp-block-code"><code>{
  "Serilog": {
    "MinimumLevel": "Information",
    "WriteTo": [
      {
        "Name": "MSSqlServer",
        "Args": {
          "connectionString": "Data Source=LAPTOP-ULJMOJQ5;Initial
           Catalog=Research;    
     User Id=joydip; Password=sa123#;",
          "tableName": "Log",
          "autoCreateSqlTable": true
        }
      }
    ]
  }
}</code></pre>



<h2 class="wp-block-heading">Create a database table to log data in SQL Server</h2>



<p>You might want to create the log table yourself as well. Below is the script you can use to create a log table in the SQL Server database.</p>



<pre class="wp-block-code"><code>CREATE TABLE [Log] (
   [Id] int IDENTITY(1,1) NOT NULL,
   [Message] nvarchar(max) NULL,
   [MessageTemplate] nvarchar(max) NULL,
   [Level] nvarchar(max) NULL,
   [TimeStamp] datetimeoffset(7) NOT NULL,
   [Exception] nvarchar(max) NULL,
   [Properties] nvarchar(max) NULL
   CONSTRAINT [PK_Log]
     PRIMARY KEY CLUSTERED ([Id] ASC)
)</code></pre>



<p>When you run the application, a new table named Log will be created and the ASP.NET Core startup events will be logged there. Figure 1 below shows the data that has been logged inside the Log table.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="447" class="wp-image-2816" src="https://topreviewhostingasp.net/wp-content/uploads/2020/12/image_1-1024x447.jpg" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2020/12/image_1-1024x447.jpg 1024w, https://topreviewhostingasp.net/wp-content/uploads/2020/12/image_1-300x131.jpg 300w, https://topreviewhostingasp.net/wp-content/uploads/2020/12/image_1-768x335.jpg 768w, https://topreviewhostingasp.net/wp-content/uploads/2020/12/image_1-50x22.jpg 50w, https://topreviewhostingasp.net/wp-content/uploads/2020/12/image_1.jpg 1200w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Log data in action methods in ASP.NET Core</h2>



<p>You can leverage dependency injection to inject a logger instance in your controller as shown in the code snippet below:</p>



<pre class="wp-block-code"><code>public class DefaultController : Controller
{
   private readonly ILogger&lt;DefaultController&gt; _logger;
   public DefaultController(ILogger&lt;DefaultController&gt; logger)
   {
      _logger = logger;
   }
}</code></pre>



<p>The following code snippet illustrates how you can take advantage of Serilog in your controller’s action methods to log data.</p>



<pre class="wp-block-code"><code>public class DefaultController : Controller
    {
        private readonly ILogger&lt;DefaultController&gt; _logger;
        public DefaultController(ILogger&lt;DefaultController&gt; logger)
        {
            _logger = logger;
        }
        public IActionResult Index()
        {
            _logger.LogInformation("Hello World");
            return View();
        }
    }</code></pre>



<p>Although independent of .NET Core, Serilog plugs into the ASP.NET Core ecosystem nicely, making structured logging easy and convenient. Serilog also takes advantage of <a href="https://github.com/serilog/serilog/wiki/Provided-Sinks">dozens of sinks</a> to send the logs to many different logging targets ranging from text files to databases to hosting providers. I will post other interesting post in next post.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/use-serilog-asp-net-core-to-sql-server-database/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Customize ASP.NET Core Default UI</title>
		<link>https://topreviewhostingasp.net/how-to-customize-asp-net-core-default-ui/</link>
					<comments>https://topreviewhostingasp.net/how-to-customize-asp-net-core-default-ui/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 17 Nov 2020 06:07:05 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net core 3.1]]></category>
		<category><![CDATA[asp net core 3.1 tips]]></category>
		<category><![CDATA[asp.net core]]></category>
		<category><![CDATA[asp.net core tips]]></category>
		<category><![CDATA[asp.net core tutorial]]></category>
		<category><![CDATA[dotnet core]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2792</guid>

					<description><![CDATA[ASP.NET Core Identity includes a default UI as a Razor library that enables you to quickly add users to an application, without having to build all the UI yourself. The downside is that if you want to customise any of the pages associated with the default UI, then you end up taking ownership of all [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>ASP.NET Core Identity includes a default UI as a Razor library that enables you to quickly add users to an application, without having to build all the UI yourself. The downside is that if you want to customise any of the pages associated with the default UI, then you end up taking ownership of all the logic too. Even if all you want to do is add a CSS class to an element, you&#8217;re stuck maintaining the underlying page handler logic too.</p>



<p>In this post I show how you can replace the Razor views for the default UI, without taking ownership of the business logic stored in the Razor Page <code>PageModel</code> code-behind files. I show how you can use the ASP.NET Core Identity scaffolder to generate the replacement Razor Pages initially, but customise these to use the <em>existing</em>, default, PageModels.</p>



<h2 class="wp-block-heading">ASP.NET Core Identity</h2>



<p>ASP.NET Core Identity is a series of services that provide functionality for managing and signing in users. You can use the Identity services to (among other things):</p>



<p>ASP.NET Core Identity is a series of services that provide functionality for managing and signing in users. You can use the Identity services to (among other things):</p>



<ul>
<li>Create users, and provide sign-in functionality</li>
<li>Secure passwords using best practice, strong, hashing algorithms</li>
<li><a href="https://docs.microsoft.com/en-gb/aspnet/core/security/authentication/accconfirm?view=aspnetcore-3.1#require-email-confirmation">Generate short-lived tokens for email confirmation</a> or <a href="https://docs.microsoft.com/en-us/aspnet/core/security/authentication/mfa?view=aspnetcore-3.1">multi-factor authentication</a>,</li>
<li>Enable <a href="https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-configuration?view=aspnetcore-3.1#lockout">auto-lockout</a> of users to prevent brute-force attacks.</li>
<li><a href="https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/?view=aspnetcore-3.1">Allow logging in with third-party providers</a> like Google and Facebook.</li>
</ul>



<p>The Identity services provide APIs for achieving all these things, but you still have to arrange them all in the right order. You also have to write the UI that users use to interact with the services. Obviously, that&#8217;s a <em>huge</em> investment, and is working with sensitive data, so you have to be very careful not to introduce any security holes.</p>



<p>Prior to ASP.NET Core 2.1, your best bet for implementing this was to use the UI generated from the Visual Studio templates. Unfortunately, using templates means that your UI is fine initially, but you then have a <em>lot</em> of code to maintain. If a bug is found in the templates, you have to go and update it yourself.</p>



<p>Luckily, ASP.NET Core 2.1 introduced a default UI Razor Class Library that meant you could benefit from the same UI, without having dozens of Razor Pages in your application to maintain. If a bug is found in the UI, the NuGet package can be updated, and you seamlessly get the bug fix, and all is great.</p>



<h2 class="wp-block-heading" id="customising-the-default-ui">Customising the default UI</h2>



<p>Of course, using the default UI means: you have to use the default UI. I think it&#8217;s generally unlikely that users will want to use the default UI in its entirety, unless you&#8217;re building internal apps only, or creating a &#8220;throwaway&#8221; app. For a start, the login and register pages include references to developer documentation that most people will want to remove:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="617" class="wp-image-2806" src="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_1-3-1024x617.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_1-3-1024x617.png 1024w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_1-3-300x181.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_1-3-768x463.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_1-3-1536x926.png 1536w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_1-3-2048x1234.png 2048w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_1-3-50x30.png 50w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Even though the UI is contained in a Razor Class Library, you can &#8220;overwrite&#8221; individual pages, by placing your own Razor Pages in a &#8220;magic&#8221; location in your project. For example, to override the register page, you can create a Razor Page at <em>Areas/Identity/Pages/Register.cshtml</em>:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="708" class="wp-image-2794" src="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_2-1-1024x708.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_2-1-1024x708.png 1024w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_2-1-300x207.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_2-1-768x531.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_2-1-50x35.png 50w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_2-1.png 1247w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>A valid concern would be &#8220;how do I know which pages I can override?&#8221;. Luckily there&#8217;s a .NET Core tool you can use to scaffold pages from Identity in the correct locations, along with supporting files.</p>



<h2 class="wp-block-heading" id="scaffolding-identity-files-with-the-net-cli">Scaffolding Identity files with the .NET CLI</h2>



<p><a href="https://docs.microsoft.com/aspnet/core/security/authentication/scaffold-identity">The documentation for scaffolding Identity pages is excellent</a>, so I&#8217;ll just run through the basics with the .NET CLI here. You can also use Visual Studio, but be sure to follow steps 1-3 below, otherwise you get weird random errors when running the scaffolder.<br /><br />1. Add all the required packages to your application. If you&#8217;re already using EF Core in your app, then you may already have some of these, but make sure they&#8217;re all there, as missing packages can cause frustrating errors locally</p>



<pre class="wp-block-code"><code>dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.Identity.UI
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>Also make sure that the installed package versions match your project version, for example .NET Core 3.1 projects should use packages starting 3.1.x.</em></p>
</blockquote>



<p>2. Confirm your project builds without errors. If it doesn&#8217;t you&#8217;ll get errors when scaffolding files.</p>



<p>3. Install the code generator tool globally using <code>dotnet tool install -g dotnet-aspnet-codegenerator</code>.</p>



<p>4. Run <code>dotnet aspnet-codegenerator identity -lf</code> from the <em>project</em> folder (not the solution folder), to see the list of files you can scaffold:</p>



<pre class="wp-block-code"><code>&gt;  dotnet aspnet-codegenerator identity -lf
Building project ...
Finding the generator 'identity'...
Running the generator 'identity'...
File List:
Account._StatusMessage
Account.AccessDenied
Account.ConfirmEmail
Account.ConfirmEmailChange
Account.ExternalLogin
Account.ForgotPassword
Account.ForgotPasswordConfirmation
Account.Lockout
... 25 more not shown!</code></pre>



<p>In this case, I&#8217;m going to scaffold the Account.Register page, and remove the external login provider section completely.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>You can create a Razor Pages app using the default UI by running </em><code>dotnet new webapp -au Individual -uld</code></p>
</blockquote>



<p>If you&#8217;re scaffolding into a project that&#8217;s configured to use the default UI, you will already have an EF Core <code>IdentityDbContext</code> in your application. Pass the fully namespaced name of the context in the following command, using the <code>-dc</code> switch, when scaffolding your files:</p>



<pre class="wp-block-code"><code>dotnet aspnet-codegenerator identity -dc TestApp.Data.ApplicationDbContext --files "Account.Register"
</code></pre>



<p>After running this command, you&#8217;ll find a bunch more files in the <em>Areas/Identity</em> folder:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="584" class="wp-image-2807" src="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_3-3-1024x584.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_3-3-1024x584.png 1024w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_3-3-300x171.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_3-3-768x438.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_3-3-1536x877.png 1536w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_3-3-2048x1169.png 2048w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_3-3-50x29.png 50w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>The generated pages override the equivalents in the default UI package, so any changes you make to <em>Register.cshtml</em> will be reflected in your app. For example, I can delete the external login provider section entirely:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="617" class="wp-image-2808" src="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_4-3-1024x617.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_4-3-1024x617.png 1024w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_4-3-300x181.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_4-3-768x463.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_4-3-1536x926.png 1536w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_4-3-2048x1234.png 2048w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_4-3-50x30.png 50w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading" id="remove-your-liabilities-deleting-the-scaffolded-pagemodel">Remove your liabilities &#8211; deleting the scaffolded PageModel</h2>



<p>I don&#8217;t want that code, so I&#8217;m just going to delete it! As I&#8217;m only going to make changes to the Razor views, I can delete the following files:</p>



<ul>
<li><em>Areas/Identity/Pages/Account/Register.cshtml.cs</em> — this is the <code>PageModel</code> implementation I don&#8217;t want to have to maintain</li>
<li><em>Areas/Identity/Pages/Account/ViewImports.cshtml</em> — No longer necessary, as there&#8217;s nothing in the namespace it specifies now</li>
<li><em>Areas/Identity/Pages/_ValidationScriptsPartial.cshtml</em> — A duplicate of the version included in the default UI. No need to override it</li>
<li><em>Areas/Identity/Pages/IdentityHostingStartup.cs</em> — Doesn&#8217;t actually configure anything, so can be deleted</li>
</ul>



<p>Additionally, you can update <em>Areas/Identity/Pages/ViewImports.cshtml</em> to remove the project-specific namespaces, to leave just the following:</p>



<pre class="wp-block-code"><code>@using Microsoft.AspNetCore.Identity
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers</code></pre>



<p>At this point, your app won&#8217;t compile. The <em>Register.cshtml</em> page will complain that you&#8217;ve specified a now non-existent <code>RegisterModel</code> as the <code>PageModel</code> for the Razor Page:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="152" class="wp-image-2804" src="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_5-2-1024x152.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_5-2-1024x152.png 1024w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_5-2-300x44.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_5-2-768x114.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_5-2-1536x228.png 1536w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_5-2-2048x303.png 2048w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_5-2-50x7.png 50w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>The final step is to update the <code>@page</code> directive to point to the <em>original</em> <code>RegisterModel</code> that&#8217;s included with the default Identity UI, referenced in full in the example below:</p>



<pre class="wp-block-code"><code>@page
@model Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Internal.RegisterModel
@{
    ViewData["Title"] = "Register";
}</code></pre>



<p>This is the magic step. Your application will now compile, use your custom Razor views, but use the <em>original</em> Razor Pages <code>PageModel</code>s that are part of the default UI! That&#8217;s much less code to maintain, and less chance to screw something up in your Identity pages</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="561" class="wp-image-2805" src="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_6-2-1024x561.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_6-2-1024x561.png 1024w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_6-2-300x164.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_6-2-768x421.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_6-2-1536x842.png 1536w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_6-2-50x27.png 50w, https://topreviewhostingasp.net/wp-content/uploads/2020/11/image_6-2.png 1597w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading" id="what-are-the-downsides-">What are the downsides?</h2>



<p>So what are the downsides of this approach? The only one I can really think of is that you&#8217;re very tightly tied to the <code>PageModel</code>s in the original Identity UI, so you have to be sure that any updates that are made to the Identity UI are reflected in your Razor Page templates as appropriate. The big advantage is that if the default UI package is updated and it doesn&#8217;t make any breaking changes to the Razor templates, then you get the updates with no friction at all.</p>



<p>Another danger is that the inability to customise the <code>PageModel</code> <em>may</em> encourage you to do slightly janky things like <code>@inject</code>-ing services into the Razor views that shouldn&#8217;t be there, and adding additional logic into the Razor views. I&#8217;m not suggesting you should do this. If you _do_ need to change the behaviour of the page handlers, then you should just go ahead and take ownership of that code. The point is that this technique is useful when you <em>don&#8217;t</em> need to change the page handler logic.</p>



<h2 class="wp-block-heading" id="summary">Summary</h2>



<p>In this post I gave some background on ASP.NET Core Identity and the default UI Razor Class Library that provides over 30 Razor Pages &#8220;for free&#8221;. I then showed how you could use the scaffolder tool to override one of these pages when you want to change the Razor template.</p>



<p>The downside of this default approach is that you now have to maintain the page handlers for the scaffolded pages. That&#8217;s 100s of lines of code per page that you must keep up to date when a new package version is released.</p>



<p>I showed how you can avoid that burden by deleting the scaffolded <code>PageModel</code> file, and point your Razor template to the <em>original</em> <code>PageModel</code> that comes as part of the default UI. This lets you update your Razor templates without having to take ownership of the page handler logic, potentially giving you the best of both worlds.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-customize-asp-net-core-default-ui/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Run .NET Core Generic as Windows Service</title>
		<link>https://topreviewhostingasp.net/how-to-run-net-core-generic-as-windows-service/</link>
					<comments>https://topreviewhostingasp.net/how-to-run-net-core-generic-as-windows-service/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 29 Oct 2019 04:41:34 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net core windows service]]></category>
		<category><![CDATA[asp.net core]]></category>
		<category><![CDATA[asp.net core tips]]></category>
		<category><![CDATA[asp.net core tutorial]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2769</guid>

					<description><![CDATA[Net Core 2.2 provides Web Host for hosting web applications and Generic Host that is suitable for hosting a wider array of host apps. In the .Net Core 3 Generic Host will replace Web Host.  Generic Host will be suitable for hosting any kind of app including web applications. I looked at many examples but found that none showed [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Net Core 2.2 provides <a href="https://topreviewhostingasp.net/best-asp-net-core-3-hosting/">Web Host</a> for hosting web applications and <a href="https://docs.microsoft.com/en-au/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.2" target="_blank" rel="noreferrer noopener">Generic Host</a> that is suitable for hosting a wider array of host apps. In the .Net Core 3 Generic Host will replace Web Host.  Generic Host will be suitable for hosting any kind of app including web applications.</p>



<p>I looked at many examples but found that none showed the complete implementation of the Generic Host that is implemented to run as a console, Linux daemon, and Windows Service all in one application.</p>



<p>Here we will be looking at extending sample_service_hosting app to run it as a console app, windows service, or Linux daemon as well as making it self installable windows service.</p>



<p>.Net Core provides <em>IHostBuilder</em> interface to configure and create host builder. In case of a console app, host builder will run <em>await RunConsoleAsync()</em> function. To host and run our Generic Host as Windows Service we will need to use <em>IApplicationLifetime</em> to register Start and Stop events.</p>



<p>For hosting our Generic Host in Linux daemon we are going to inject <em>IApplicationLifetime</em> into main service and register and handle Start and Stop events.</p>



<p>There are several ways we could go to extend it to run as Windows Service, console app and Linux daemon. One way is to have a separate .Net Core project that will host our sample generic host service for each case or allow the program to accept command line variables that specify how to run the program. We will implement the command line arguments.</p>



<p><strong>Command-line options:</strong></p>



<ul>
<li>-i    Install as Windows Service</li>
<li>-u  Uninstall Windows Service</li>
<li>-console Run as a console app</li>
<li>-daemon Run as Linux daemon service</li>
<li>-h  Show command line switch help</li>
</ul>



<h2 class="wp-block-heading">Let’s make Argument Parser</h2>



<p>In order to parse the arguments passed to the application, we will implement an argument parser class, which will return <em>HostAction</em> enum that specifies how the application is going to start. The application will accept only one argument on its input. If more than one argument supplied or it is an invalid argument, it will show usage message. If no arguments supplied it will try to run as Windows Service.</p>



<h3 class="wp-block-heading">HostAction enum</h3>



<pre class="wp-block-code"><code>namespace VSC
{
    public enum HostAction
    {
        ShowUsage,
        InstallWinService,
        UninstallWinService,
        RunWinService,
        WinServiceStop,
        RunConsole,
        RunLinuxDaemon
    }
}</code></pre>



<h3 class="wp-block-heading">Argument Parser class – ArgsParser</h3>



<pre class="wp-block-code"><code>namespace VSC
{
    internal class ArgsParser
    {
        private string[] _args = null;
        public ArgsParser(string[] args)
        {
            _args = args;
        }

        public HostAction GetHostAction()
        {
            HostAction action = HostAction.ShowUsage;

            if(_args == null || _args.Length == 0)
            {
                action = HostAction.RunWinService;
            }
            else if(_args.Length &gt; 1)
            {
                action = HostAction.ShowUsage;
            }
            else
            {
                string argument = _args[0];

                if(argument == "-i")    // install
                {
                    action = HostAction.InstallWinService;
                }
                else if(argument == "-u")   // uninstall
                {
                    action = HostAction.UninstallWinService;
                }
                else if(argument == "-console")
                {
                    action = HostAction.RunConsole;
                }
                else if (argument == "-daemon")
                {
                    action = HostAction.RunLinuxDaemon;
                }
            }

            return action;
        }
    }
}</code></pre>



<h2 class="wp-block-heading">Let’s make HostedService class</h2>



<p>At the moment sample_service_hosting app creates host builder by calling <em>CreateHostBuilder()</em> from the Main function. We need to introduce a class that will perform an action depending on what HostAction returned by ArgsParser. We will call it <em>HostedService</em> class. It will have an async Run function that will start different action.</p>



<p>For now let’s implement run as a console, run as Linux daemon and show usage actions. Function <em>CreateHostBuilder()</em> will be moved from Program.cs to <em>HostedService</em> class.</p>



<h3 class="wp-block-heading">HostedService class</h3>



<pre class="wp-block-code"><code>using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NLog.Extensions.Hosting;

namespace VSC
{
    internal class HostedService
    {
        private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();

        private ArgsParser _argsParser = null;

        public HostedService(ArgsParser argsParser)
        {
            _argsParser = argsParser;
        }

        public async Task Run(string[] args)
        {
            if (_argsParser != null)
            {
                var builder = this.CreateHostBuilder(args);
                
                if(builder == null) return;

                switch (_argsParser.GetHostAction())
                {
                    case HostAction.InstallWinService:
                    {
                        
                    }
                    break;
                    case HostAction.UninstallWinService:
                    {
                        
                    }
                    break;
                    case HostAction.RunWinService:
                    {
                        
                    }
                    break;
                    case HostAction.RunConsole:
                    {
                        try
                        {
                            await builder.RunConsoleAsync();
                        }
                        catch(Exception ex)
                        {
                            _logger.Error("Could not run as console app. " + ex.Message);
                            ShowUsage();
                        }
                    }
                    break;
                    case HostAction.RunLinuxDaemon:
                    {
                        try
                        {
                            await builder.Build().RunAsync();
                        }
                        catch(Exception ex)
                        {
                            _logger.Error("Could not start as Linux daemon service. " + ex.Message);
                            ShowUsage();
                        }
                    }
                    break;
                    default:
                    {
                        ShowUsage();
                    }
                    break;
                } 
            }   
        }

        private void ShowUsage()
        {   
            Console.WriteLine("Options:\n"
                        + "  'no options'\tStart Windows Service\n"
                        + "  -i\t\tInstall as Windows Service\n"
                        + "  -u\t\tUninstall Windows Service\n"
                        + "  -console\tRun as console app\n"
                        + "  -daemon\t Run as Linux daemon service\n"
                        + "  -h\t\tShow command line switch help\n");
        }
        private IHostBuilder CreateHostBuilder(string[] args)
        {
            try
            {
                var builder = new HostBuilder()
                    .UseNLog()
                    .ConfigureAppConfiguration((hostingContext, config) =&gt;
                    {
                        config.SetBasePath(Directory.GetCurrentDirectory());
                        config.AddJsonFile("appsettings.json", optional: true);
                        config.AddJsonFile(
                            $"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", 
                            optional: true);
                        config.AddCommandLine(args);
                    })
                    .ConfigureServices((hostContext, services) =&gt;
                    {
                        services.AddHostedService&lt;Services.SampleService&gt;();
                        services.Configure&lt;HostOptions&gt;(option =&gt;
                        {
                            option.ShutdownTimeout = System.TimeSpan.FromSeconds(20);
                        });
                    })
                    .ConfigureLogging((hostingContext, logging) =&gt; 
                    {
                        logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                        logging.AddConsole();
                    });

                return builder;
            }
            catch { }

            return null;
        }
    }
}</code></pre>



<p>In Program.cs we change code as follows.</p>



<h3 class="wp-block-heading">Program.cs</h3>



<pre class="wp-block-code"><code>using System.Threading.Tasks;

namespace VSC
{
    class Program
    {   
        static async Task Main(string[] args)
        {
            ArgsParser argsParser = new ArgsParser(args);

            HostedService service = new HostedService(argsParser);
            await service.Run(args);
        }
    }
}</code></pre>



<h2 class="wp-block-heading">Let’s Make it self installable Windows Service</h2>



<p>Now we got to the point of making our sample app to run as Windows Service. As Software Developer we always try to make the life of our users easier. If the app will be able to self install/uninstall as windows service our users will be much happier than trying to do that themselves.</p>



<p>We will start in the external process <em>sc.exe</em> service controller tool with parameters to install/uninstall/stop service. Example:<ins></ins></p>



<ul>
<li>sc.exe create “service_name” displayname= “service_name” binpath= “path to exe file”</li>
<li>sc.exe delete “service_name”</li>
<li>sc.exe stop “service_name”</li>
</ul>



<p><em>WinServiceInstaller</em> class will be responsible for running an external process and notifying of the progress. We will use <em>WinService</em> class to handle Start, Stop events and use extension functions to inject our WinService class into our Generic Host Builder.</p>



<h3 class="wp-block-heading">WinService class</h3>



<pre class="wp-block-code"><code>using System;
using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;

namespace VSC
{
    public class WinService : ServiceBase, IHostLifetime
    {
        public static string WinServiceName = "Default Service Name";
        private readonly TaskCompletionSource&lt;object&gt; _delayStart = new TaskCompletionSource&lt;object&gt;();

        private IApplicationLifetime ApplicationLifetime { get; }

        public WinService(IApplicationLifetime applicationLifetime)
        {
            this.ServiceName = WinServiceName;

            ApplicationLifetime = applicationLifetime ?? throw new ArgumentNullException(nameof(applicationLifetime));
        }        

        public void Start()
        {
            try
            {
                Run(this); // This blocks until the service is stopped.
                _delayStart.TrySetException(new InvalidOperationException("Stopped without starting"));
            }
            catch (Exception ex)
            {
                _delayStart.TrySetException(ex);
            }

            this.OnStart(null);
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            Stop();
            return Task.CompletedTask;
        }

        public Task WaitForStartAsync(CancellationToken cancellationToken)
        {
            cancellationToken.Register(() =&gt; _delayStart.TrySetCanceled());
            ApplicationLifetime.ApplicationStopping.Register(Stop);

            new Thread(Start).Start(); // Otherwise this would block and prevent IHost.StartAsync from finishing.
            return _delayStart.Task;
        }

        protected override void OnStart(string[] args)
        {
            _delayStart.TrySetResult(null);
            base.OnStart(args);
        }

        protected override void OnStop()
        {
            ApplicationLifetime.StopApplication();
            base.OnStop();
        }
    }
}</code></pre>



<h3 class="wp-block-heading">WinServiceInstaller class</h3>



<pre class="wp-block-code"><code>using System.Diagnostics;

namespace VSC
{
    public static class WinServiceInstaller
    {
        private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();

        public static string APP_EXECUTABLE_PATH = string.Empty;
        private const string ServiceControllerEXE = "sc.exe";

        public delegate void WinServiceStatusHandler (string status);
        public static event WinServiceStatusHandler WinServiceStatus;

        public static void Uninstall(string serviceName)
        {
            Stop(serviceName); // stop service before uninstall

            RaiseWinServiceStatus("Uninstall Service");

            RunProcess(string.Format("delete \"{0}\"", serviceName));
        }

        private static void Stop(string serviceName)
        {
            RaiseWinServiceStatus("Stopping Service");

            RunProcess(string.Format("stop \"{0}\"", serviceName));            
        }

        public static void Install(string serviceName)
        {
            if(!string.IsNullOrEmpty(APP_EXECUTABLE_PATH))
            {
                RaiseWinServiceStatus("Install Service");

                string processArguments = string.Format("create \"{0}\" displayname= \"{1}\" binpath= \"{2}\"", serviceName, serviceName, APP_EXECUTABLE_PATH);
                
                RunProcess(processArguments);
            }
            else
            {
                _logger.Error("Cannot install service. Path to exe cannot be empty.");
            }
        }

        private static void RaiseWinServiceStatus(string status)
        {
            if(WinServiceStatus != null)
            {
                WinServiceStatus(status);
            }
        }

        private static void RunProcess(string arguments)
        {
            _logger.Trace("Arguments: " + arguments);

            var process = new Process();
            var processInfo = new ProcessStartInfo();
            processInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            processInfo.FileName = ServiceControllerEXE;
            processInfo.Arguments = arguments;
            process.StartInfo = processInfo;
            process.Start();
            process.WaitForExit();
        }
    }
}</code></pre>



<h3 class="wp-block-heading">WinServiceExtensions static class</h3>



<pre class="wp-block-code"><code>using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace VSC
{
    public static class WinServiceExtensions
    {
        internal static IHostBuilder UseServiceBaseLifetime(this IHostBuilder hostBuilder)
        {
            return hostBuilder.ConfigureServices((hostContext, services) =&gt; services.AddSingleton&lt;IHostLifetime, WinService&gt;());
        }

        public static Task RunAsWindowsServiceAsync(this IHostBuilder hostBuilder, CancellationToken cancellationToken = default)
        {
            return hostBuilder.UseServiceBaseLifetime().Build().RunAsync(cancellationToken);
        }
    }
}</code></pre>



<p>We need to add to our project package reference <em>System.ServiceProcess.ServiceController</em> in order to compile <em>WinService</em> class.</p>



<pre class="wp-block-code"><code>dotnet add package System.ServiceProcess.ServiceController</code></pre>



<p>Now in <em>HostedService</em> Run function, we can implement remaining switch cases that will Install, Uninstall and Run our app as windows service.</p>



<pre class="wp-block-code"><code>internal class HostedService
{
    ...

    public async Task Run(string[] args)
    {
        if (_argsParser != null)
        {
            var builder = this.CreateHostBuilder(args);
                
            if(builder == null) return;

            WinServiceInstaller.APP_EXECUTABLE_PATH = Utility.GetExecutingAssemblyLocation().Remove(Utility.GetExecutingAssemblyLocation().Length - 4) + ".exe";
                
            switch (_argsParser.GetHostAction())
            {
                case HostAction.InstallWinService:
                {
                    WinServiceInstaller.Install(WinService.WinServiceName);
                }
                break;
                case HostAction.UninstallWinService:
                {
                    WinServiceInstaller.Uninstall(WinService.WinServiceName);
                }
                break;
                case HostAction.RunWinService:
                {
                    try
                    {
                        await builder.RunAsWindowsServiceAsync();
                    }
                    catch(Exception ex)
                    {
                        _logger.Error("Could not start as windows service. " + ex.Message);
                        ShowUsage();
                    }
                }
                break;

    ...
}</code></pre>



<p>You may have noticed that APP_EXECUTABLE_PATH is set by calling utility function <em>GetExecutingAssemblyLocation</em> in Utility class.</p>



<h3 class="wp-block-heading">Utility static class</h3>



<pre class="wp-block-code"><code>namespace VSC
{
    public static class Utility
    {
        public static string GetExecutingAssemblyLocation()
        {
            return System.Reflection.Assembly.GetExecutingAssembly().Location;
        }
    }
}</code></pre>



<h2 class="wp-block-heading">Let’s update the Main function</h2>



<p>As the final step, we will update our Program.cs and add the logger to print status of our Windows Service. At the end before closing application, we also need to Flush logger and shut it down to release resource when our app will run as Linux daemon.</p>



<h3 class="wp-block-heading">Program.cs</h3>



<pre class="wp-block-code"><code>using System;
using System.Threading.Tasks;
using NLog;
using System.Reflection;

namespace VSC
{
    class Program
    {   
        private static Logger _logger = NLog.LogManager.GetCurrentClassLogger();

        static async Task Main(string[] args)
        {
            ArgsParser argsParser = new ArgsParser(args);

            WinService.WinServiceName = "The Sample Service Host";
            WinServiceInstaller.WinServiceStatus += new WinServiceInstaller.WinServiceStatusHandler(PrintWinServiceStatus);

            _logger.Info("Version: " + Assembly.GetEntryAssembly().GetName().Version.ToString());

            HostedService service = new HostedService(argsParser);
            await service.Run(args);

            _logger.Info("Shutting down logger...");
            // Flush buffered log entries before program exit; then shutdown the logger before program exit.
            LogManager.Flush(TimeSpan.FromSeconds(15));
            LogManager.Shutdown();
        }

        private static void PrintWinServiceStatus(string status)
        {
            _logger.Info(status);
        }
    }
}</code></pre>



<h2 class="wp-block-heading">Summary</h2>



<p>Today we extended sample_service_hosting app with the ability to run as windows service and self install/uninstall itself to make it easier to deploy as windows service. We could go down the path of implementing separate projects: one for a console app, one for Linux daemon, one for windows service and one common project with our SampleService Host. We managed to do it all in one project with the use of ArgsParser class and extension functions to inject our Host into <em>WinService</em>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-run-net-core-generic-as-windows-service/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Top 13 ASP.NET Core Features that You MUST Try</title>
		<link>https://topreviewhostingasp.net/13-asp-net-core-features/</link>
					<comments>https://topreviewhostingasp.net/13-asp-net-core-features/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Wed, 09 Jan 2019 04:11:33 +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 Hosting]]></category>
		<category><![CDATA[cheap ASP.NET Hosting]]></category>
		<category><![CDATA[development asp.net core]]></category>
		<category><![CDATA[reason to use asp.net]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2641</guid>

					<description><![CDATA[ASP.NET is one of the most successful web application development frameworks by Microsoft. With every update, new and extended features are added that help developers deploy highly scalable and high-performance web applications. When coupled with application monitoring and other performance tools, such as a profiler, ASP.NET becomes a powerful solution for building incredible apps. Within the framework itself, there [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>ASP.NET is one of the most successful web application development frameworks by Microsoft. With every update, new and extended features are added that help developers deploy highly scalable and high-performance web applications.</p>
<p>When coupled with application monitoring and other performance tools, such as a profiler, ASP.NET becomes a powerful solution for building incredible apps.</p>
<p>Within the framework itself, there are myriad features to help you overcome common development challenges, do more with your apps, and boost performance.</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2642" src="https://topreviewhostingasp.net/wp-content/uploads/2019/01/asp-net-core.png" alt="" width="288" height="175" srcset="https://topreviewhostingasp.net/wp-content/uploads/2019/01/asp-net-core.png 288w, https://topreviewhostingasp.net/wp-content/uploads/2019/01/asp-net-core-50x30.png 50w" sizes="(max-width: 288px) 100vw, 288px" /></p>
<h2>13 features to build better applications with ASP.NET Core</h2>
<h3>1. Cross-platform &amp; container support</h3>
<p>With the introduction of .NET Core, you can now create ASP.NET applications and deploy them to <strong>Windows, Linux, and macOS</strong>. Microsoft and the community have put a huge effort into making Linux a first-class citizen for running ASP.NET.</p>
<p>Containers are eating the clouds these days. Docker, Kuberenetes and other technologies are all the rage. ASP.NET Core allows developers to utilize all of these new technologies. Microsoft Azure even has support for deploying your application to containers and Kubernetes.</p>
<h3>2. High performance</h3>
<p>Some say that performance is a critical feature of your software. I tend to agree! With the introduction of ASP.NET Core and the Kestrel web server, ASP.NET is touted as one of the fastest web application frameworks available. <a href="https://www.techempower.com/benchmarks/" target="_blank" rel="noopener noreferrer">TechEmpower</a> has some cool benchmarks you can check out.</p>
<p>The technology that powered the ASP.NET integrated pipeline and IIS was roughly 15 years old. It did everything and carried a lot of baggage with it. The new Kestrel web server was redesigned from the ground up to take advantage of asynchronous programming models, be much more lightweight, and fast!</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2643" src="https://topreviewhostingasp.net/wp-content/uploads/2019/01/kestrel.png" alt="" width="1501" height="875" srcset="https://topreviewhostingasp.net/wp-content/uploads/2019/01/kestrel.png 1501w, https://topreviewhostingasp.net/wp-content/uploads/2019/01/kestrel-300x175.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2019/01/kestrel-768x448.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2019/01/kestrel-1024x597.png 1024w, https://topreviewhostingasp.net/wp-content/uploads/2019/01/kestrel-50x29.png 50w" sizes="(max-width: 1501px) 100vw, 1501px" /></p>
<h3>3. Asynchronous via async/await</h3>
<p>ASP.NET has excellent support for utilizing asynchronous programming patterns. Async is now implemented in all common .NET Framework classes and most third-party libraries. Most modern applications spend most of their time and CPU cycles waiting for database queries, web service calls, and other I/O operations to complete.</p>
<p>One of the reasons ASP.NET Core is faster is its extensive use of asynchronous patterns within the new MVC and Kestrel frameworks.</p>
<pre class="prettyprint prettyprinted"><span class="com">//mark the method as async</span>
<span class="kwd">public</span> <span class="kwd">async</span> <span class="typ">Task</span> <span class="typ">GetGWB</span><span class="pun">()</span>
<span class="pun">{</span>
    <span class="typ">HttpClient</span><span class="pln"> hc </span><span class="pun">=</span> <span class="kwd">new</span> <span class="typ">HttpClient</span><span class="pun">();</span>
    <span class="com">//await keyword handles all the complexity of async threading and callbacks</span>
    <span class="kwd">await</span><span class="pln"> hc</span><span class="pun">.</span><span class="typ">GetAsync</span><span class="pun">(</span><span class="str">"http://geekswithblogs.net/Default.aspx"</span><span class="pun">);</span>
    <span class="kwd">return</span> <span class="kwd">true</span><span class="pun">;</span>
<span class="pun">}</span></pre>
<h3><a href="http://www.asphostportal.com"><img loading="lazy" decoding="async" class="size-full wp-image-2584 alignleft" src="https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01.png" alt="" width="300" height="271" 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>4. Unified MVC &amp; Web API frameworks</h3>
<p>Before ASP.NET Core, developers were most commonly using the MVC and Web API frameworks. MVC was tailored to creating web applications that served up HTML. Web API was designed to create RESTful services using JSON or XML.</p>
<p>With ASP.NET Core, MVC and Web API have been merged together. There was always a lot of overlap with the two frameworks. MVC could always return JSON data instead of HTML. Combining them was a good move and simplifies development.</p>
<p>With ASP.NET Core we also have the new Razor Pages. They extend the MVC framework to allow encapsulating the controller and model aspects of a page together with two-way binding. They are sort of a replacement for WebForms while using the familiar Razor syntax.</p>
<h3>5. Multiple environments and development mode</h3>
<p>One of my favorite features is the new environment feature. It allows you to easily differentiate parts of your code for their behavior in development, staging, production, etc. There was no standard way to do this before ASP.NET Core.</p>
<p>Environments are perfect for using different CSS or Javascript files. Use your CDN in production, but local files during development. This is a snippet out of my Razor layout view.</p>
<pre class="prettyprint prettyprinted">    <span class="tag">&lt;environment</span> <span class="atn">names</span><span class="pun">=</span><span class="atv">"Development"</span><span class="tag">&gt;</span>
        <span class="tag">&lt;script</span> <span class="atn">src</span><span class="pun">=</span><span class="atv">"~/lib/jquery/dist/jquery.js"</span><span class="tag">&gt;&lt;/script&gt;</span>
        <span class="tag">&lt;script</span> <span class="atn">src</span><span class="pun">=</span><span class="atv">"~/lib/bootstrap/dist/js/bootstrap.js"</span><span class="tag">&gt;&lt;/script&gt;</span>
        <span class="tag">&lt;script</span> <span class="atn">src</span><span class="pun">=</span><span class="atv">"~/js/site.js"</span> <span class="atn">asp-append-version</span><span class="pun">=</span><span class="atv">"true"</span><span class="tag">&gt;&lt;/script&gt;</span>
    <span class="tag">&lt;/environment&gt;</span>
    <span class="tag">&lt;environment</span> <span class="atn">names</span><span class="pun">=</span><span class="atv">"Staging,Production"</span><span class="tag">&gt;</span>
        <span class="tag">&lt;script</span> <span class="atn">src</span><span class="pun">=</span><span class="atv">"https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"</span>
                <span class="atn">asp-fallback-src</span><span class="pun">=</span><span class="atv">"~/lib/jquery/dist/jquery.min.js"</span>
                <span class="atn">asp-fallback-test</span><span class="pun">=</span><span class="atv">"window.jQuery"</span>
                <span class="atn">crossorigin</span><span class="pun">=</span><span class="atv">"anonymous"</span>
                <span class="atn">integrity</span><span class="pun">=</span><span class="atv">"sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk"</span><span class="tag">&gt;</span>
        <span class="tag">&lt;/script&gt;</span>
        <span class="tag">&lt;script</span> <span class="atn">src</span><span class="pun">=</span><span class="atv">"https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"</span>
                <span class="atn">asp-fallback-src</span><span class="pun">=</span><span class="atv">"~/lib/bootstrap/dist/js/bootstrap.min.js"</span>
                <span class="atn">asp-fallback-test</span><span class="pun">=</span><span class="atv">"window.jQuery &amp;&amp; window.jQuery.fn &amp;&amp; window.jQuery.fn.modal"</span>
                <span class="atn">crossorigin</span><span class="pun">=</span><span class="atv">"anonymous"</span>
                <span class="atn">integrity</span><span class="pun">=</span><span class="atv">"sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"</span><span class="tag">&gt;</span>
        <span class="tag">&lt;/script&gt;</span>
        <span class="tag">&lt;script</span> <span class="atn">src</span><span class="pun">=</span><span class="atv">"~/js/site.min.js"</span> <span class="atn">asp-append-version</span><span class="pun">=</span><span class="atv">"true"</span><span class="tag">&gt;&lt;/script&gt;</span>
    <span class="tag">&lt;/environment&gt;</span></pre>
<h3>6. Dependency Injection</h3>
<p>One of the great new features of ASP.NET Core is built in dependency injection. It is heavily used within ASP.NET MVC itself. It is the preferred way that things like logging contexts, database contexts, and other things are passed into your MVC controllers.</p>
<pre class="prettyprint prettyprinted"><span class="kwd">public</span> <span class="kwd">class</span> <span class="typ">PaymentService</span><span class="pun">:</span> <span class="typ">IPaymentService</span>
<span class="pun">{</span>
  <span class="kwd">public</span> <span class="typ">ILogger</span> <span class="typ">Logger</span> <span class="pun">{</span> <span class="kwd">get</span><span class="pun">;</span> <span class="pun">}</span>

  <span class="com">//automatically passes the logger factory in to the constructor via dependency injection</span>
  <span class="kwd">public</span> <span class="typ">PaymentService</span><span class="pun">(</span><span class="typ">ILoggerFactory</span><span class="pln"> loggerFactory</span><span class="pun">)</span>
  <span class="pun">{</span>
    <span class="typ">Logger</span> <span class="pun">=</span><span class="pln"> loggerFactory</span><span class="pun">?.</span><span class="typ">CreateLogger</span><span class="pun">();</span>
    <span class="kwd">if</span><span class="pun">(</span><span class="typ">Logger</span> <span class="pun">==</span> <span class="kwd">null</span><span class="pun">)</span>
    <span class="pun">{</span>
      <span class="kwd">throw</span> <span class="kwd">new</span> <span class="typ">ArgumentNullException</span><span class="pun">(</span><span class="pln">nameof</span><span class="pun">(</span><span class="pln">loggerFactory</span><span class="pun">));</span>
    <span class="pun">}</span>
    <span class="typ">Logger</span><span class="pun">.</span><span class="typ">LogInformation</span><span class="pun">(</span><span class="str">"PaymentService created"</span><span class="pun">);</span>
  <span class="pun">}</span>
<span class="pun">}</span></pre>
<h3>7. WebSockets &amp; SignalR</h3>
<p>ASP.NET has first class support for <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/websockets" target="_blank" rel="noopener noreferrer">WebSockets</a>. This can be used to persist long running connections and communicate back and forth with the browser. SignalR is a full framework that is also available that makes it easy handle common scenarios.</p>
<h3>8. Cross-Site Request Forgery (CSRF) Protection</h3>
<p>Security is important. It is also one of those things that can be a lot of work to prevent certain types of attacks. CSRF is in referencing to hijacking users authenticated session to perform an action that they did not initiate.</p>
<p>For example, let’s pretend that you log in to your bank account and then navigate to a different website. If that other website could do a POST to your bank website to transfer funds, that would be a bad thing. It could potentially do that if your online session on the banking website is valid and the bank does not properly validate requests.</p>
<p>ASP.NET has a good framework that is available to prevent these types of attacks. It generates anti-forgery tokens.</p>
<h3>9. “Self hosted” Web Applications</h3>
<p>Sometimes you need to make a web application that will be deployed on to a desktop and not a server running IIS. Our free ASP.NET profiler, Prefix, is a perfect example of this. Its front end is all HTML that is loaded from an ASP.NET application running as a Windows Service.</p>
<p>You can create a self-hosted ASP.NET web application several different ways. In .NET 4.5 you could accomplish it by using Owin, Nancy, or WCF. For Prefix, we use ASP.NET Web API with Owin.</p>
<p>With ASP.NET Core, you can also use the standard Kestrel web server. One of the great advantages of .NET Core is that your web application is essentially a console application. IIS just sits in front of it as a reverse proxy. This means that you can also deploy your app only with kestrel for non-server based use cases, like Prefix.</p>
<h3>10. Action Filters</h3>
<p>One of the great features of ASP.NET is the support for extensible filters. This allows you to implement functionality that can be applied to an entire controller or action without modifying the action itself.</p>
<p>Filters are used to specify caching, error handling, authorization, or any custom logic you would like to implement.</p>
<pre class="prettyprint prettyprinted"><span class="kwd">using</span> <span class="typ">System</span><span class="pun">;</span>
<span class="kwd">using</span> <span class="typ">System</span><span class="pun">.</span><span class="typ">Web</span><span class="pun">.</span><span class="typ">Mvc</span><span class="pun">;</span>

<span class="kwd">namespace</span> <span class="typ">MvcApplication1</span><span class="pun">.</span><span class="typ">Controllers</span>
<span class="pun">{</span><span class="pln">
     </span><span class="kwd">public</span> <span class="kwd">class</span> <span class="typ">DataController</span> <span class="pun">:</span> <span class="typ">Controller</span><span class="pln">
     </span><span class="pun">{</span><span class="pln">
          </span><span class="pun">[</span><span class="typ">OutputCache</span><span class="pun">(</span><span class="typ">Duration</span><span class="pun">=</span><span class="lit">10</span><span class="pun">)]</span><span class="pln">
          </span><span class="kwd">public</span> <span class="kwd">string</span> <span class="typ">Index</span><span class="pun">()</span><span class="pln">
          </span><span class="pun">{</span><span class="pln">
               </span><span class="kwd">return</span> <span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Now</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">(</span><span class="str">"T"</span><span class="pun">);</span><span class="pln">
          </span><span class="pun">}</span><span class="pln">
     </span><span class="pun">}</span>
<span class="pun">}</span></pre>
<h3>11. Extensible Output Caching</h3>
<p>This feature allows ASP.NET to cache the output generated by a page and serve this cached content for future requests. It stores the data that is not updated frequently and outputs that specific data from a cached location.</p>
<p>ASP.NET makes it easy to specify how long any request should be cached via common HTTP headers. It also has support for caching output within the memory on your web server itself. You can even use <a href="https://docs.microsoft.com/en-us/azure/redis-cache/cache-aspnet-output-cache-provider" target="_blank" rel="noopener noreferrer">Redis</a> or other providers to handle your output caching.</p>
<h3>12. Globalization and Localization</h3>
<p>ASP.NET makes it easy to localize dates, numbers, and the text within your web application. If you want your application to be used across the globe, localization will be very important to you.</p>
<p>ASP.NET enables customizing your application for multiple languages via resource files. These resource files are considered as the central repository where all texts are kept, and web pages can read this resource file and get labels populated. There are two types of resources:</p>
<ul>
<li>Local Resources – specific for a page (i.e., there will be local resource file for every page)</li>
<li>Global Resources – common for the whole website (i.e., one resource file accessed by all pages)</li>
</ul>
<h3>13. Swagger OpenAPI</h3>
<p>If you are creating API applications, you want to make sure you are using <a href="https://swagger.io/" target="_blank" rel="noopener noreferrer">Swagger</a>. It makes it easy to document and test your APIs.</p>
<p>ASP.NET has historically provided built-in functionality that is pretty similar for SOAP web services created with WCF. If you are using Web API or MVC for RESTful APIs, you definitely want to use Swagger.</p>
<h2>Conclusion</h2>
<p>ASP.NET Core has been a nice upgrade over previous versions. In this article, we highlighted some of the key features you should be aware of. Some are new, some are just key features of ASP.NET that have existed for a while.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/13-asp-net-core-features/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Host ASP.NET Core 2.0 Application in Docker</title>
		<link>https://topreviewhostingasp.net/how-to-host-asp-net-core-2-0-application-in-docker/</link>
					<comments>https://topreviewhostingasp.net/how-to-host-asp-net-core-2-0-application-in-docker/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Fri, 10 Aug 2018 05:10:00 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp.net core docker]]></category>
		<category><![CDATA[asp.net core tips]]></category>
		<category><![CDATA[asp.net core tutorial]]></category>
		<category><![CDATA[asp.net host on docker]]></category>
		<category><![CDATA[asp.net on docker]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=2219</guid>

					<description><![CDATA[In today&#8217;s article, we will create an ASP.NET Core 2.0 MVC web application with Docker support and then, we will deploy our application in a Docker container (Windows 10). Why do we need this? The main purpose of Docker is to deploy applications to the production environment or other environments as required by Ops. However, [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In today&#8217;s article, we will create an ASP.NET Core 2.0 MVC web application with Docker support and then, we will deploy our application in a Docker container (Windows 10).</p>
<p><strong>Why do we need this?</strong></p>
<p>The main purpose of Docker is to deploy applications to the production environment or other environments as required by Ops. However, the highlight of Docker lies in the process of deploying it.</p>
<p>Till Docker came into the picture, the traditional approach to deployment was via Virtual Machines (VM). And let’s not get started with the drawbacks of VMs because there are a plenty. Starting from the effort required to boot a VM, to launching multiple VMs in the same machine, it is a tough task to get things running with VMs.</p>
<p>So first, let’s see what does Docker provide?</p>
<p>Docker provides a container environment which can be used to host any application of your choice. The software application and the dependencies which support it are <em>tightly-packaged</em> together.</p>
<p>This packaged product is called a Container. Since it is done by Docker, it is called a Docker container!</p>
<p><strong>Benefits of Docker container?</strong></p>
<p>Since the application and its dependencies are packaged together, there is no external dependency for the app to run. This means the container is very light-weight.</p>
<p>Because it is light-weight, it can be easily shipped to other machines and be executed on those machines, irrespective of their host OS/ configurations.</p>
<p>The only requirement being, <em>Docker has to be installed</em> to run that application residing in the container.</p>
<p>So let&#8217;s get started.</p>
<p>We will install docker for windows (we are using windows 10).</p>
<p>For that go to the following link &#8211; <em>https://store.docker.com/editions/community/docker-ce-desktop-windows</em></p>
<p>You will need to login in order to download this. Once you have downloaded the setup and installed then restart your system.</p>
<p>After restarting go to command prompt and type docker version</p>
<p>You should see something like this in your console.</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2220" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_1.png" alt="" width="601" height="314" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_1.png 601w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_1-300x157.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_1-50x26.png 50w" sizes="(max-width: 601px) 100vw, 601px" /></p>
<p>It means that docker is successfully installed in your machine. Now we will create our ASP.NET Core 2.0 MVC application.</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2221" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_2.jpg" alt="" width="602" height="420" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_2.jpg 602w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_2-300x209.jpg 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_2-50x35.jpg 50w" sizes="(max-width: 602px) 100vw, 602px" /></p>
<p>Make sure to check Enable Docker Support  checkbox and select your OS (mine is windows)</p>
<p>Once the project is created then you will see some docker files in the solution explorer,</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2222" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_3.png" alt="" width="324" height="342" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_3.png 324w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_3-284x300.png 284w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_3-47x50.png 47w" sizes="(max-width: 324px) 100vw, 324px" /></p>
<p>When we open Dockerfile,</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2223" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_4.png" alt="" width="544" height="378" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_4.png 544w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_4-300x208.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_4-50x35.png 50w" sizes="(max-width: 544px) 100vw, 544px" /></p>
<p>These are the contents of the auto-generated file.</p>
<p>What this file does is defines the dependencies which are required for our application and when we host our application in docker then this file is read by the docker to get the dependencies and get the entry point for our application.</p>
<p>So our application part is done. Now we will simply host our application in the docker container.</p>
<p>For that open command prompt and go to the project location where DockerFile resides and type docker-compose build and hit enter.</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2224" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_5.png" alt="" width="602" height="109" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_5.png 602w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_5-300x54.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_5-50x9.png 50w" sizes="(max-width: 602px) 100vw, 602px" /></p>
<p>You will see some processes, let them execute</p>
<p>After all the steps are done you should see something like this,</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2225" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_6.png" alt="" width="506" height="161" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_6.png 506w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_6-300x95.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_6-50x16.png 50w" sizes="(max-width: 506px) 100vw, 506px" /></p>
<p>After this to see the images type docker images and hit enter,</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2226" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_7.png" alt="" width="602" height="106" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_7.png 602w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_7-300x53.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_7-50x9.png 50w" sizes="(max-width: 602px) 100vw, 602px" /></p>
<p>You should see your application like this. So this is our image. But the image is just a template, we cannot connect to it, to run it we have to put this image inside a container and the run that container. So for that, we will copy its image id and type docker run your_image_id,</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2227" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_8.png" alt="" width="602" height="116" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_8.png 602w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_8-300x58.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_8-50x10.png 50w" sizes="(max-width: 602px) 100vw, 602px" /></p>
<p>As you can see now our application is running. So to open it in our browser we need IP address of our container which has the image. To check that type docker ps –a and hit enter,</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2228" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_9.png" alt="" width="602" height="83" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_9.png 602w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_9-300x41.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_9-50x7.png 50w" sizes="(max-width: 602px) 100vw, 602px" /></p>
<p>Here we can see our container that is just been created and now to get the IP address of our container type docker inspect your_container_id</p>
<p>It will give you information about your container like this</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2229" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_10.png" alt="" width="602" height="300" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_10.png 602w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_10-300x150.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_10-50x25.png 50w" sizes="(max-width: 602px) 100vw, 602px" /></p>
<p>You will get all of this information, now scroll down and look for NetworkSettings</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2230" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_11.png" alt="" width="601" height="436" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_11.png 601w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_11-300x218.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_11-50x36.png 50w" sizes="(max-width: 601px) 100vw, 601px" /></p>
<p>You will need this highlighted IP address.</p>
<p>There is another way to get this IP Address and that is to type the following</p>
<p>docker inspect -f &#8220;{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}&#8221;  your_container_id</p>
<p style="text-align: center;"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2231" src="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_12.png" alt="" width="602" height="57" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_12.png 602w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_12-300x28.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/08/image_12-50x5.png 50w" sizes="(max-width: 602px) 100vw, 602px" /></p>
<p>So now that we have got the IP address just enter this address in the browser. And you can see that your application running on a docker container.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-host-asp-net-core-2-0-application-in-docker/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
