<?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 &#8211; ASP.NET Hosting Reviews and Guides</title>
	<atom:link href="https://topreviewhostingasp.net/tag/asp-net/feed/" rel="self" type="application/rss+xml" />
	<link>https://topreviewhostingasp.net</link>
	<description>ASP.NET Hosting &#124; Reviews &#124; Tips &#38; Tutorial</description>
	<lastBuildDate>Fri, 22 Sep 2023 05:16:14 +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 &#8211; ASP.NET Hosting Reviews and Guides</title>
	<link>https://topreviewhostingasp.net</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Grow Your ASP.NET Website with ASPHostPortal</title>
		<link>https://topreviewhostingasp.net/grow-your-asp-net-website-with-asphostportal/</link>
					<comments>https://topreviewhostingasp.net/grow-your-asp-net-website-with-asphostportal/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Fri, 22 Sep 2023 05:16:14 +0000</pubDate>
				<category><![CDATA[Press Release]]></category>
		<category><![CDATA[asp net]]></category>
		<category><![CDATA[asp net ecommerce hosting]]></category>
		<category><![CDATA[asp net hosting]]></category>
		<category><![CDATA[asphostportal]]></category>
		<category><![CDATA[best asp net hosting]]></category>
		<category><![CDATA[cheap asp net hosting]]></category>
		<category><![CDATA[reliable asp net hosting]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=3734</guid>

					<description><![CDATA[This trustworthy seller lost out on a sale due to a bad user experience, specifically a slow website. This is both a significant and solvable issue. In fact, Google has long claimed that a website&#8217;s ranking in its search engine results pages (SERPs), particularly on mobile devices, depends on a variety of factors, including how [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>This trustworthy seller lost out on a sale due to a bad user experience, specifically a slow website. This is both a significant and solvable issue. In fact, Google has long claimed that a website&#8217;s ranking in its search engine results pages (SERPs), particularly on mobile devices, depends on a variety of factors, including how quickly a page loads.</p>
<p>A web page should load in no more than 2 seconds, according to Google. Google, however, aims for <a href="https://www.semrush.com/blog/how-fast-is-fast-enough-page-load-time-and-your-bottom-line/" target="_blank" rel="noopener">0.8 seconds</a> or less. Therefore, even if a business has the best products in the world, its overall reach — whether it comes from paid or organic traffic — will be limited if it&#8217;s coupled with a poor web experience for users.</p>
<p>A reputable authority in the ASP.NET community and a premium ASP.NET hosting provider, <a href="https://www.asphostportal.com" target="_blank" rel="noopener">ASPHostPortal</a>. The team at the company is passionate about informing customers about the importance of web performance as it provides highly effective yet user-friendly tools and services.</p>
<p><img fetchpriority="high" decoding="async" class="wp-image-3589 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2023/06/asphostportal-managed-hosting-min.jpg" alt="" width="734" height="616" srcset="https://topreviewhostingasp.net/wp-content/uploads/2023/06/asphostportal-managed-hosting-min.jpg 940w, https://topreviewhostingasp.net/wp-content/uploads/2023/06/asphostportal-managed-hosting-min-300x251.jpg 300w, https://topreviewhostingasp.net/wp-content/uploads/2023/06/asphostportal-managed-hosting-min-768x644.jpg 768w, https://topreviewhostingasp.net/wp-content/uploads/2023/06/asphostportal-managed-hosting-min-50x42.jpg 50w" sizes="(max-width: 734px) 100vw, 734px" /></p>
<p>We had a conversation with Dean, VP Marketing, to gain a deeper understanding of how ASPHostPortal can improve site performance and thereby increase the potential profits of its partners. Dean explains how ASPHostPortal wants to stop its customers&#8217; high bounce rates and unrealized profits.</p>
<h2 class="wp-block-heading">ASPHostPortal responds to the demand for more ASP.NET Users</h2>
<p>The COVID-19 pandemic has altered many aspects of life in the world, including how we communicate and conduct business. Dean claims that ASPHostPortal saw a seemingly overnight change in the digital market.</p>
<p>Many of our customers, who had never done so before, were rushing to create some kind of ASP.NET and ecommerce component, according to Dean. &#8220;Restaurants had not made as much progress as retailers in their transition from brick-and-mortar to digital.</p>
<p>Many restaurants did not have curbside pickup or delivery options, and then they all appeared at once.</p>
<p>The team at ASPHostPortal faced an uphill battle with the rapid increase in businesses closing down (or at least supplementing) their physical locations. The business unveiled a platform for managing and billing for agency clients as well as a new hosting service for online shops. Together, these product launches bolster ASPHostPortal&#8217;s dominance in the ASP.NET hosting market and give users the ability to reduce the milliseconds that matter most in online business.</p>
<h2>40% Faster ASP.NET Sites and 22% More Sales Thanks to New Platform</h2>
<p>Websites like Ecommerce, a hugely popular WordPress plugin for online stores, are catered to by the new ASP.NET hosting service from ASPHostPortal. Dean claims that the platform uses compute-optimized infrastructure, a variety of ASP.NET-specific add-ons, and optimizations to deliver online storefronts up to 40% faster.</p>
<p>According to Dean, &#8220;the platform offloads a lot of dynamic ASP.NET requests, making your site faster — up to 20% faster in our performance tests and possibly more depending on how the site is configured.&#8221; &#8220;For customers who have switched to that particular service, we&#8217;ve seen up to an 20% increase in sales.&#8221;</p>
<p><a href="https://www.asphostportal.com" target="_blank" rel="noopener"><img decoding="async" class="size-full wp-image-2584 aligncenter" 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></p>
<p>The value of ASPHostPortal goes beyond performance to include security, another important aspect of successful online store operations. Consider ASP.NET updates as an example. Although the well-known scripting language is frequently used in the creation of dynamic websites, managing its necessary software updates can be difficult for non-developers, i.e., the majority of online store owners. Dean stated that at the time of this interview, 18% of all ASP.NET sites were using unpatched or unsafe versions of ASP.NET.</p>
<p>Dean stated, &#8220;There is a security patch available, and all of our customers are using patched versions. &#8220;We provide our customers with the means to perform (the maintenance) on their own. We support them when they don&#8217;t, though.</p>
<h2>Summary: Use ASPHostPortal to increase ASP.NET site performance and revenue.</h2>
<p>ASPHostPortal has been promoting its clients&#8217; high-speed ASP.NET sites with higher realized profits for more than ten years. ASPHostPortal constantly pushes the limits of what is possible as a recognized leader in the ASP.NET innovation space. The company&#8217;s dedication to promoting growth for its customers is reaffirmed by the most recent launches of eCommerce products.</p>
<p>A faster website will result in fewer bounces, according to Dean. Numerous studies have demonstrated the advantages of that performance. Conversion rates and your capacity to launch products more quickly are everything.</p>
<p>ASPHostPortal doesn&#8217;t have a bargain-basement price; instead, the hosting company is totally committed to the long-term value it offers to clients who are able to see it.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/grow-your-asp-net-website-with-asphostportal/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Custom Output Caching in ASP.NET Core</title>
		<link>https://topreviewhostingasp.net/custom-output-caching-in-asp-net-core/</link>
					<comments>https://topreviewhostingasp.net/custom-output-caching-in-asp-net-core/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 01 Aug 2023 04:26:24 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net]]></category>
		<category><![CDATA[asp net core]]></category>
		<category><![CDATA[asp net core tutorial]]></category>
		<category><![CDATA[caching asp net core]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=3648</guid>

					<description><![CDATA[Background Once a page has been cached in the browser (or proxy), the server cannot make the cached copy be utilized in place of the updated version. Pages that are likely to change cannot, therefore, be cached at the client for very long. There is nothing we can do to change this. We should have [&#8230;]]]></description>
										<content:encoded><![CDATA[<h2>Background</h2>
<p>Once a page has been cached in the browser (or proxy), the server cannot make the cached copy be utilized in place of the updated version. Pages that are likely to change cannot, therefore, be cached at the client for very long. There is nothing we can do to change this.</p>
<p>We should have greater control at the server, but sadly, the built-in response caching prevents cache invalidation. Additionally, it employs the same cache duration for asking the browser to cache the page and for server-side caching. Some apps cannot use the built-in response caching due to these limitations.</p>
<p>We are going to investigate developing a unique response caching system. We&#8217;ll presum the following conditions:</p>
<ul>
<li>Allow server and client cache durations to be different</li>
<li>Allow an arbitrary page to be removed from the cache at will</li>
<li>Allow multiple cached pages to be removed based on a common criterion (tags)</li>
</ul>
<p>The fundamental prerequisite is the capacity for endless caching at the server and the ability for application code to invalidate current cache entries when content changes.</p>
<p>Additionally, we&#8217;ll prioritize efficiency and quickness over adaptability. IMemoryCache will be used to implement the cache for a single web server. It is simple to go from using IMemoryCache to IDistributedCache in web farm scenarios, however because of this interface&#8217;s less features, the third criteria (tagged) cannot be met without a redesign.</p>
<h2>Implementation</h2>
<p>We will implement our caching as middleware that runs before MVC and can short-circuit the entire request pipeline if a cached page is found in order to enable it to be as quick as feasible.</p>
<p>We have the following flow for a page that is not in the cache:</p>
<ol>
<li>Fail to retrieve page from the cache</li>
<li>Execute inner middleware (the MVC pipeline) redirecting the response to a buffer</li>
<li>Cache the page (if conditions are met)</li>
<li>Render page</li>
</ol>
<p>The sequence is substantially shorter for a page that has already been cached:</p>
<ol>
<li>Retrieve page from cache</li>
<li>Render page</li>
</ol>
<p>The quickest way to return cached material is using middleware, but it is more challenging to allow specific page cache setup. The middleware might be utilized independently if all pages were cached using the same criteria, but for the majority of real-world sites, we require the ability to control which pages are cached and for how long. Although middleware configuration might be used, using attributes on controller actions is considerably simpler.</p>
<h3>Controlling server caching</h3>
<p>We&#8217;ll use a very basic action filter attribute to let us manage how specific pages are cached:</p>
<pre><code>public class CacheAttribute : ActionFilterAttribute
{
    public int? ClientDuration { get; set; }
    public int? ServerDuration { get; set; }
    public string Tags { get; set; }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // validation omitted

        if (ClientDuration.HasValue)
        {
            context.HttpContext.Items[Constants.ClientDuration] = ClientDuration.Value;
        }

        if (ServerDuration.HasValue)
        {
            context.HttpContext.Items[Constants.ServerDuration] = ServerDuration.Value;
        }

        if (!string.IsNullOrWhiteSpace(Tags))
        {
            context.HttpContext.Items[Constants.Tags] = Tags;
        }

        base.OnActionExecuting(context);
    }
}</code></pre>


<p>The filter&#8217;s simple implementation only adds the attribute values to the collection of HttpContext Items. To communicate between the operation and the middleware for caching, we are using the collection.</p>



<h3 class="wp-block-heading">The middleware</h3>



<p>The primary Invoke method of the middleware is quite readable:</p>



<pre class="wp-block-code"><code>public async Task Invoke(HttpContext context)
{
    var key = BuildCacheKey(context);

    if (_cache.TryGet(key, out CachedPage page))
    {
        await WriteResponse(context, page);

        return;
    }

    ApplyClientHeaders(context);

    if (IsNotServerCachable(context))
    {
        await _next.Invoke(context);

        return;
    }            

    page = await CaptureResponse(context);

    if (page != null)
    {
        var serverCacheDuration = GetCacheDuration(context, Constants.ServerDuration);

        if (serverCacheDuration.HasValue)
        {
            var tags = GetCacheTags(context, Constants.Tags);

            _cache.Set(key, page, serverCacheDuration.Value, tags);
        }
    }            
}</code></pre>



<p>Your requirements will determine how you construct the cache key, however it may only require the use of context.Request.Path.</p>



<p>The request is finished if the page can be retrieved from the cache and written to the response.</p>



<pre class="wp-block-code"><code>private async Task WriteResponse(HttpContext context, CachedPage page)
{
    foreach (var header in page.Headers)
    {
        context.Response.Headers.Add(header);
    }

    await context.Response.Body.WriteAsync(page.Content, 0, page.Content.Length);
}</code></pre>



<p>If a cached page cannot be located, additional effort must be done. In order to determine if we may cache the request, we first set any necessary client caching headers. If another method is used, we call the following middleware component and stop processing the request because we only wish to cache GET methods.</p>



<p>Capturing the request output from internal middleware components is the next step. In the part after this, we go over how this is accomplished. If we&#8217;ve set up server side caching (using the action filter mentioned above), the last step is to save the page to the cache.</p>



<h3 class="wp-block-heading">Capturing the response</h3>



<p>You must replace the response body stream&#8217;s default with a MemoryStream in order to capture the page response:</p>



<pre class="wp-block-code"><code>private async Task&lt;CachedPage> CaptureResponse(HttpContext context)
{
    var responseStream = context.Response.Body;

    using (var buffer = new MemoryStream())
    {
        try
        {
            context.Response.Body = buffer;

            await _next.Invoke(context);
        }
        finally
        {
            context.Response.Body = responseStream;
        }

        if (buffer.Length == 0) return null;

        var bytes = buffer.ToArray(); // you could gzip here

        responseStream.Write(bytes, 0, bytes.Length);

        if (context.Response.StatusCode != 200) return null;

        return BuildCachedPage(context, bytes);
    }
}</code></pre>



<p>We return null and make no attempt to cache the response if nothing has been written to it or if the status code is not 200. If not, a CachedPage instance is returned:</p>



<pre class="wp-block-code"><code>internal class CachedPage
{
    public byte&#91;] Content { get; private set; }
    public List&lt;KeyValuePair&lt;string, StringValues>> Headers { get; private set; }

    public CachedPage(byte&#91;] content)
    {
        Content = content;
        Headers = new List&lt;KeyValuePair&lt;string, StringValues>>();
    }
}</code></pre>



<p>The content of the cached page is combined with a subset of the response headers, some of which should be removed (for example, the date header).</p>



<h3 class="wp-block-heading">Controlling client caching</h3>



<p>We choose the straightforward method when it comes to providing caching headers to the browser:</p>



<pre class="wp-block-code"><code>public void ApplyClientHeaders(HttpContext context)
{
    context.Response.OnStarting(() =>
    {
        var clientCacheDuration = GetCacheDuration(context, Constants.ClientDuration);

        if (clientCacheDuration.HasValue &amp;&amp; context.Response.StatusCode == 200)
        {
            if (clientCacheDuration == TimeSpan.Zero)
            {
                context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue
                {
                    NoCache = true,
                    NoStore = true,
                    MustRevalidate = true
                };
                context.Response.Headers&#91;"Expires"] = "0";
            }
            else
            {
                context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue
                {
                    Public = true,
                    MaxAge = clientCacheDuration
                };
            }
        }

        return Task.CompletedTask;
    });            
}</code></pre>



<p>Keep in mind that our action filter determines the ClientDuration value. There are three possibilities:</p>



<ul><li>Unset &#8211; do not send headers</li><li>Zero &#8211; set various headers instructing downstream clients not to cache the response</li><li>Other &#8211; set the cache headers to the provided value</li></ul>



<h3 class="wp-block-heading">The cache</h3>



<p>We haven&#8217;t yet talked about the actual cache, which is one thing. The _cache references in the code above really correspond to a wrapper class that contains the IMemoryCache implementation that is built-in.</p>



<pre class="wp-block-code"><code>public class CacheClient : ICacheClient
{
    private readonly IMemoryCache _cache;
    
    public CacheClient(IMemoryCache cache)
    {
        _cache = cache ?? throw new ArgumentNullException(nameof(cache));
    }

    internal bool TryGet&lt;T>(string key, out T entry)
    {
        return _cache.TryGetValue(Constants.CacheKeyPrefix + key, out entry);
    }

    internal void Set(string key, object entry, TimeSpan expiry, params string&#91;] tags)
    {
        var options = new MemoryCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = expiry
        };

        var allTokenSource = _cache.GetOrCreate(Constants.CacheTagPrefix + Constants.AllTag, 
            allTagEntry => new CancellationTokenSource());

        options.AddExpirationToken(new CancellationChangeToken(allTokenSource.Token));

        foreach (var tag in tags)
        {
            var tokenSource = _cache.GetOrCreate(Constants.CacheTagPrefix + tag, tagEntry =>
            {
                tagEntry.AddExpirationToken(new CancellationChangeToken(allTokenSource.Token));

                return new CancellationTokenSource();
            });

            options.AddExpirationToken(new CancellationChangeToken(tokenSource.Token));
        }

        _cache.Set(Constants.CacheKeyPrefix + key, entry, options);
    }</code></pre>



<p>Expiration tokens are used by the Set function to enable bulk removal of cache entries.</p>



<p>The concept is that we store a CancellationTokenSource for every entry in the cache and additional CancellationTokenSources for each tag we define. If you have never used CancellationTokenSource before, this may be a little difficult to understand. When setting the cache entry, we produce a token by using these CancellationTokenSources. In the following part, we&#8217;ll look at using the CancellationTokenSources to invalidate cache items in bulk.</p>



<h2 class="wp-block-heading">Cache invalidation AKA cache busting</h2>



<p>This unique kind of response caching was implemented primarily to meet the need for the ability to delete cache items before they naturally expire. The following methods are exposed by our CacheClient class for this:</p>



<pre class="wp-block-code"><code>public void Remove(string key)
{
    _cache.Remove(Constants.CacheKeyPrefix + key);
}

public void RemoveByTag(string tag)
{
    if (_cache.TryGetValue(Constants.CacheTagPrefix + tag, out CancellationTokenSource tokenSource))
    {
        tokenSource.Cancel();

        _cache.Remove(Constants.CacheTagPrefix + tag);
    }            
}

public void RemoveAll()
{
    RemoveByTag(Constants.AllTag);
}</code></pre>



<p>As you can see, deleting a single cache entry just requires that you know the key. You could want to allow action, controller, and route values to be given instead to make it more user-friendly.</p>



<p>The RemoveAll and RemoveByTag methods invoke the Cancel() function, which expires all tokens issued by the source, after retrieving the CancellationTokenSource from the cache. These cache entries are eliminated as a result.</p>



<h3 class="wp-block-heading">Limitations</h3>



<p>This is a very simple illustration of response caching and is devoid of many features found in native response caching middleware. The lack of the option to alter caching depending on headers, cookies, etc. is perhaps the most noticeable missing. It would not be extremely challenging to incorporate VaryBy. In reality, all we&#8217;re altering is how the cache key is generated and adding support for CacheAttribute setting.</p>



<p>Additionally, we are using IMemoryCache rather than IDistributedCache, which is more scalable. As was already said, modifying the usage is simple but will reduce functionality. Since IDistributedCache does not allow expiration tokens, the method described here cannot be used to remove pages in bulk. Naturally, nothing prevents you from coming up with a different approach, but unsophisticated implementations will almost surely have a negative impact on performance.</p>



<h2 class="wp-block-heading">Summary</h2>



<p>The creation of simple response caching middleware that enables manual invalidation of items both individually and in bulk using tags was covered in this post. To store pages (or other action results like JSON) in an in-memory cache, we combined an action filter with a middleware component. Then, we made a number of methods available on our CacheClient class to enable the deletion of cache entries.</p>



<p>The example code should not be used in place of the built-in response caching, which offers far more capability, although it might be helpful in some circumstances.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/custom-output-caching-in-asp-net-core/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>4 Simple Steps to Deploy ASP.NET Core in IIS</title>
		<link>https://topreviewhostingasp.net/4-simple-steps-to-deploy-asp-net-core-in-iis/</link>
					<comments>https://topreviewhostingasp.net/4-simple-steps-to-deploy-asp-net-core-in-iis/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 25 Jul 2023 03:34:42 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net]]></category>
		<category><![CDATA[asp net core]]></category>
		<category><![CDATA[asp net core iis]]></category>
		<category><![CDATA[asp net core tips]]></category>
		<category><![CDATA[asp net core tutorial]]></category>
		<category><![CDATA[host asp net core iis]]></category>
		<category><![CDATA[iis tips]]></category>
		<category><![CDATA[iis tutorial]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=3638</guid>

					<description><![CDATA[Deploying an ASP.NET Core app to IIS isn’t complicated. However, ASP.NET Core hosting is different compared to hosting with ASP.NET, because ASP.NET Core uses different configurations. IIS, on the other hand, is a web server that utilizes the Windows OS and the ASP.NET framework. IIS&#8217;s function in this situation is to host ASP.NET Core-built apps. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Deploying an ASP.NET Core app to IIS isn’t complicated. However, ASP.NET Core hosting is different compared to hosting with ASP.NET, because ASP.NET Core uses different configurations.</p>
<p>IIS, on the other hand, is a web server that utilizes the Windows OS and the ASP.NET framework. IIS&#8217;s function in this situation is to host ASP.NET Core-built apps.</p>
<p>In this article, we&#8217;ll look at how to integrate ASP.NET Core with IIS. Let&#8217;s examine the procedures for deploying ASP.NET Core to IIS without further ado.</p>
<h2>How to Setup an ASP.NET Core Application for IIS</h2>
<p>When starting a new ASP.NET Core project, you will immediately discover that it is a console application. The following code is also present in your project&#8217;s Program.cs file, which is similar to a console application:</p>
<pre class="wp-block-preformatted prettyprint">public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup()
            .Build();

        host.Run();
    }
}</pre>
<h3 id="h-what-is-the-webhostbuilder">What is the WebHostBuilder?</h3>
<p>A WebHost object—essentially the application and web server—is necessary for all ASP.NET Core applications. To configure and create the WebHost in this instance, a WebHostBuilder is utilized. Usually, the setup code for WebHostBuilder contains the statements UseKestrel() and UseIISIntegration().</p>
<p>Why do these?</p>
<ul>
<li><strong>UseKestrel()</strong> – Registers Kestrel as the server that will host your application by registering the IServer interface. Other solutions, such as the Windows-only WebListener, may become available in the future.</li>
<li><strong>UseIISIntegration()</strong> – Provides information to ASP.NET about how IIS will act as a reverse proxy in front of Kestrel, including the port it should listen on, forward headers, and other parameters.</li>
</ul>
<blockquote class="wp-block-quote"><p>If you are planning to deploy your application to IIS, UseIISIntegration() is required</p></blockquote>
<h3 id="h-what-is-aspnetcoremodule">What is AspNetCoreModule?</h3>
<p>You may have noticed that ASP.NET Core projects create a web.config file. This is only used when deploying your application to IIS and registers the <strong>AspNetCoreModule</strong> as an HTTP handler.</p>
<h3 id="h-default-web-config-for-asp-net-core">Default web.config for ASP.NET Core:</h3>
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;configuration&gt;
    &lt;system.webServer&gt;
        &lt;handlers&gt;
            &lt;add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/&gt;
        &lt;/handlers&gt;
        &lt;aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/&gt;
     &lt;/system.webServer&gt;
&lt;/configuration&gt;</pre>
<p>All incoming traffic to IIS is handled by AspNetCoreModule, which then serves as a reverse proxy that knows how to send traffic to your ASP.NET Core application. Its source code is accessible on <a href="https://github.com/aspnet/AspNetCoreModule" target="_blank" rel="noopener">GitHub</a>. Additionally, AspNetCoreModule is in charge of launching your process and making sure that your web application is up and running.</p>
<h3 id="h-install-net-core-windows-server-hosting-bundle">Install .NET Core Windows Server Hosting Bundle</h3>
<p>Installing the.NET Core hosting bundle for IIS, which includes the ASP.NET Core module for IIS and the.NET Core runtime, is necessary before you publish your application.</p>
<p>To make sure all the modifications are taken up by IIS after installation, you might need to do a &#8220;net stop was /y&#8221; and &#8220;net start w3svc&#8221; command.</p>
<p>Download: <a href="https://www.microsoft.com/net/download/all" target="_blank" rel="noopener">Windows Server Hosting for.NET Core</a> &#8211; Select &#8220;Windows Server Hosting&#8221; without a doubt.</p>
<h2 id="h-steps-to-deploy-asp-net-core-to-iis">4 Steps to Deploy ASP.NET Core to IIS</h2>
<p>Before you deploy, you need to make sure that WebHostBuilder is configured properly for Kestrel and IIS. Your web.config file should also exist and look similar to our example above.</p>
<h3 id="h-step-1-publish-to-a-file-folder">1. Publish to a File Folder</h3>
<p><img decoding="async" class="size-full wp-image-3639 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2023/07/publish-target.png" alt="" width="1024" height="672" srcset="https://topreviewhostingasp.net/wp-content/uploads/2023/07/publish-target.png 1024w, https://topreviewhostingasp.net/wp-content/uploads/2023/07/publish-target-300x197.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2023/07/publish-target-768x504.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2023/07/publish-target-50x33.png 50w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<h3 id="h-step-2-copy-files-to-preferred-iis-location">2. Copy Files to Preferred IIS Location</h3>
<p>Copy your publish output now to the location where you want the files to reside. You might want to zip up the files and transfer them to the server if you are deploying to a distant host. You can replicate them locally if you are deploying to a local development box.</p>
<p>I&#8217;m moving the files to C:\inetpub\wwwroot\AspNetCore46 for our example.</p>
<p>There is no bin folder with ASP.NET Core, and it might copy over a huge number of various.NET DLLs, as you will notice. If you are aiming for the entire.NET Framework, your application might also be an EXE file. Over 100 DLLs were produced by this tiny sample project.</p>
<p><img loading="lazy" decoding="async" class="wp-image-3640 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-file.png" alt="" width="788" height="485" srcset="https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-file.png 1024w, https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-file-300x185.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-file-768x473.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-file-50x31.png 50w" sizes="(max-width: 788px) 100vw, 788px" /></p>
<h3 id="h-step-3-create-application-in-iis">3. Create Application in IIS</h3>
<p>Creating your application in IIS is listed as a single &#8220;Step,&#8221; but you will actually do several different tasks. First, build a new IIS Application Pool with &#8220;<strong>No Managed Code</strong>&#8221; for the.NET CLR. IIS isn&#8217;t actually running any.NET code; it just functions as a reverse proxy.</p>
<p>The second option is to create your application under an already-existing or brand-new IIS Site. In any case, you must select your new IIS Application Pool and direct it to the location where you copied the ASP.NET publish output files.</p>
<p><img loading="lazy" decoding="async" class=" wp-image-3641 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-iis.png" alt="" width="768" height="571" srcset="https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-iis.png 1036w, https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-iis-300x223.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-iis-1024x761.png 1024w, https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-iis-768x571.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2023/07/aspnetcore-iis-50x37.png 50w" sizes="(max-width: 768px) 100vw, 768px" /></p>
<h3>4. Load Your Application</h3>
<p>At this point, your application should load just fine. If it does not, check the output logging from it. Within your web.config file you define how IIS starts up your ASP.NET Core process. Enable output logging by setting <strong>stdoutLogEnabled</strong>=true. You may also want to change the log output location as configured in <strong>stdoutLogFile</strong>. Check out the example web.config before to see where they are set.</p>
<h2>Where Can I Find Reliable and Cheap ASP.NET Core Hosting?</h2>
<p>The following is my recommendation for ASP.NET Core web hosting:</p>
<p><strong>1. <a href="https://www.asphostportal.com" target="_blank" rel="noopener">ASPHostPortal</a>: </strong>this is my first recommendation to host ASP.NET core website. It is a very reliable platform with a fast server and great customer support. It is a reliable ASP.NET Core hosting service for websites that do not require any special functionality or features.</p>
<p><strong>2. <a href="https://www.hostforlife.eu" target="_blank" rel="noopener">HostForLIFE.eu</a></strong>: HostForLIFE is one of the best ASP.NET core web hosting in Europe. They support all ASP.NET version, start from Classic ASP, ASP.NET 1/2.0/3.5/4.0/4.5 and latest ASP.NET Core version. It is easy to deploy ASP.NET core website to their server.</p>
<p><strong>3. <a href="https://www.UKWindowsHostASP.NET" target="_blank" rel="noopener">UKWindowsHostASP.NET</a>: </strong>One of the most reputable and affordable ASP.Net Core hosting companies in the world is UKWindowsHostASP.NET. It provides cloud hosting, VPS hosting, dedicated servers, and a wide range of adaptable alternatives for your company needs.</p>
<p><strong>4. <a href="https://www.windowsaspnethosting.in" target="_blank" rel="noopener">WindowsASPNETHosting.in</a></strong>: The finest host for developers and new businesses is WindowsASPNETHosting.in. For your web application or other project, WindowsASPNETHosting.in provides an ASP.NET, ASP,.Net Core, and SQL platform that you can easily extend with additional functionality.</p>
<p><strong>5. <a href="https://www.discountservice.biz" target="_blank" rel="noopener">DiscountService.biz</a></strong>: DiscountService committed to provide best, cheap, and reliable ASP.NET Core hosting services. They can offer you the quickest and safest platform to host your ASP.NET websites.</p>
<h2>Conclusion</h2>
<p>I hope above article can help you to publish your ASP.NET Core website easily to IIS. Instead of that, I also give some recommendation for ASP.NET core hosting in case you want to publish your ASP.NET core website online. Hope this helps and stay tune with other interesting tutorial and tips. Thank you for reading.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/4-simple-steps-to-deploy-asp-net-core-in-iis/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Fix No &#8216;Access-Control-Allow-Origin&#8217; .NET API CORS</title>
		<link>https://topreviewhostingasp.net/how-to-fix-no-access-control-allow-origin-net-api-cors/</link>
					<comments>https://topreviewhostingasp.net/how-to-fix-no-access-control-allow-origin-net-api-cors/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Wed, 14 Jun 2023 08:15:55 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net]]></category>
		<category><![CDATA[asp net tips]]></category>
		<category><![CDATA[asp net tutorial]]></category>
		<category><![CDATA[how to fix No 'Access-Control-Allow-Origin' header]]></category>
		<category><![CDATA[No 'Access-Control-Allow-Origin' header]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=3571</guid>

					<description><![CDATA[In this article, I will discuss about the error message that you might found when calling a CORS protected .NET Core Api. The following is the full error message: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In this article, I will discuss about the error message that you might found when calling a CORS protected .NET Core Api. The following is the full error message:</p>
<pre class="lang:default decode:true">Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header
is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. 
The response had HTTP status code 405.</pre>
<h2>How to Fix Error No &#8216;Access-Control-Allow-Origin&#8217;</h2>
<h3>1. Allow Method &#8220;Options&#8221;</h3>
<p>A preflight request is one that the browser sends to see if the CORS settings have been correctly implemented.</p>
<p>Therefore, if your endpoint supports POST, PUT, or DELETE operations and the browser sends a &#8220;application/json&#8221; request, the browser sends two requests: the &#8220;OPTIONS&#8221; request first, then a POST, PUT, or DELETE request.</p>
<p>You must therefore enable OPTIONS: in your application&#8217;s CORS settings.</p>
<pre class="lang:default decode:true ">app.UseCors(builder =&gt;
{
  builder
     .WithOrigins("http://localhost:4200", "https://localhost:4200")
     .SetIsOriginAllowedToAllowWildcardSubdomains()
     .AllowAnyHeader()
     .AllowCredentials()
     .WithMethods("GET", "PUT", "POST", "DELETE", "OPTIONS")
     .SetPreflightMaxAge(TimeSpan.FromSeconds(3600));
}
);</pre>
<h3>2. Cors is Defined Twice in Your Code</h3>
<p>Check that you have defined CORS twice.</p>
<p>First add CORS to the <strong>WebApplicationBuilder </strong>Services:</p>
<pre class="lang:default decode:true ">var builder = WebApplication.CreateBuilder();
...
...
builder.Services.AddCors();</pre>
<p>Then when defining the app:</p>
<div>
<pre class="lang:default decode:true ">var app = builder.Build();
app.UseCors(builder =&gt;
      {
        builder
              .WithOrigins("http://localhost:4200", "https://localhost:4200")
              .SetIsOriginAllowedToAllowWildcardSubdomains()
              .AllowAnyHeader()
              .AllowCredentials()
              .WithMethods("GET", "PUT", "POST", "DELETE", "OPTIONS")
              .SetPreflightMaxAge(TimeSpan.FromSeconds(3600));
 
      }
);</pre>
<h3>3. Check the Sequence of Calls</h3>
<p>You must define CORS before you map controllers, define routes etc.</p>
</div>
<div>
<pre class="lang:default decode:true ">var app = builder.Build();
 
// The first thing in the chain of calls is to define the CORS
app.UseCors(builder =&gt;
      {
        builder
              .WithOrigins("http://localhost:4200", "https://localhost:4200")
              .SetIsOriginAllowedToAllowWildcardSubdomains()
              .AllowAnyHeader()
              .AllowCredentials()
              .WithMethods("GET", "PUT", "POST", "DELETE", "OPTIONS")
              .SetPreflightMaxAge(TimeSpan.FromSeconds(3600));
 
      }
);
 
...
...
 
// After that, I can do mapping, routing, redirection etc...
app.MapControllers();
app.UseRouting();
app.UseHttpsRedirection();
 
if (app.Environment.IsProduction())
{
  app.UseTokenAuthentication();
}
 
app.Run();</pre>
<h3>4. Your Load Balancer Must Allow &#8220;Options&#8221; as well</h3>
<p>In front of your API, do you have a load balancer? Verify that OPTIONS methods are also supported by the load balancer.</p>
<p>Hopefully, tips above help you to fix above error. Happy Coding!</p>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-fix-no-access-control-allow-origin-net-api-cors/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Use ASP.NET Identity in a Console Apps</title>
		<link>https://topreviewhostingasp.net/how-to-use-asp-net-identity-in-a-console-apps/</link>
					<comments>https://topreviewhostingasp.net/how-to-use-asp-net-identity-in-a-console-apps/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Mon, 20 Mar 2023 07:46:02 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net]]></category>
		<category><![CDATA[asp net identity]]></category>
		<category><![CDATA[asp net tips]]></category>
		<category><![CDATA[asp net tutorial]]></category>
		<category><![CDATA[asp net user authentication]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=3478</guid>

					<description><![CDATA[Your apps may implement authentication quite easily with the help of Microsoft&#8217;s ASP.NET framework. Hardly little has to be done to create a standard web application. You need to do little more than tick a few boxes to proceed. You may not be aware, though, that ASP.NET user authentication may be added to console applications. [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Your apps may implement authentication quite easily with the help of Microsoft&#8217;s ASP.NET framework. Hardly little has to be done to create a standard web application. You need to do little more than tick a few boxes to proceed.</p>



<p>You may not be aware, though, that ASP.NET user authentication may be added to console applications.</p>



<p>Thankfully, the hidden magic is mostly gone with.NET Core. All the components needed for authentication are available to you, and you are free to reuse them as necessary.</p>



<p>Making two projects—a console application and a web application—is the simplest method to do this. Make sure ASP.NET authentication is turned on in the web application before you begin.</p>



<p>All that is left to do is transfer some settings from the web application to our console application.</p>



<p>We must first include a few NuGet packages in our console application. References will be required for:</p>



<ul>
<li>Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore</li>
<li>Microsoft.AspNetCore.Identity.EntityFrameworkCore</li>
<li>Microsoft.AspNetCore.Identity.UI</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://www.asphostportal.com" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="300" height="271" class="wp-image-2584 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01-50x45.png 50w" sizes="(max-width: 300px) 100vw, 300px" /></a></figure></div>


<p>You must first construct your NuGet packages before creating the ApplicationUser class and the Entity Framework database context.</p>



<pre class="wp-block-code"><code>public class ApplicationDbContext : IdentityDbContext&lt;ApplicationUser&gt;
{
    public ApplicationDbContext(DbContextOptions&lt;ApplicationDbContext&gt; options)
        : base(options)
    {

    }

    public DbSet&lt;ApplicationUser&gt; ApplicationUsers { get; set; } 
}</code></pre>



<pre class="wp-block-code"><code>public class ApplicationUser: IdentityUser
{

}</code></pre>



<p>After getting your Entity Framework stuff set up, all that is really left to configure is your .NET Core DI.</p>



<pre class="wp-block-code"><code>public class Configurator
{
    public static void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        services.AddDbContext&lt;ApplicationDbContext&gt;(options =&gt;
            options.UseSqlite(
                configuration.GetConnectionString("DefaultConnection")));

        services.AddIdentity&lt;ApplicationUser, IdentityRole&gt;()
            .AddEntityFrameworkStores&lt;ApplicationDbContext&gt;()
            .AddDefaultTokenProviders();

        services.AddLogging();

        services.AddScoped(
            typeof(IAuthentication),
            typeof(Authentication));
    }
}</code></pre>



<p>Now that everything has been set up, we can use our console application to access ASP.NET Identity data just as we would in a web application. A example authentication service with numerous typical user-related features is shown below.</p>



<pre class="wp-block-code"><code>public class Authentication : IAuthentication
    {
        readonly UserManager&lt;ApplicationUser&gt; _userManager;

        public Authentication(UserManager&lt;ApplicationUser&gt; userManager)
        {
            _userManager = userManager;
        }
        
        public async Task&lt;User&gt; CreateUser(string email, string password)
        {
            var applicationUser = new ApplicationUser()
            {
                Email = email,
                UserName = email,
            };

            
            var result = await _userManager.CreateAsync(applicationUser, password);
            if (!result.Succeeded)
            {
                return null;
            }
            
            var loaded = await _userManager.FindByNameAsync(email);
            return DTOMapper.Map&lt;User&gt;(loaded);
        }
        
        public async Task&lt;User&gt; UpdatePassword(string email, string oldPassword, string newPassword)
        {
            var loaded1 = await _userManager.FindByNameAsync(email);
            if (loaded1 == null)
            {
                return null;
            }
            
            var result = await _userManager.ChangePasswordAsync(loaded1, oldPassword, newPassword);
            if (!result.Succeeded)
            {
                return null;
            }
            
            var loaded2 = await _userManager.FindByNameAsync(email);
            return DTOMapper.Map&lt;User&gt;(loaded2);
        }
        
        public async Task&lt;bool&gt; CheckPassword(string email, string password)
        {
            var loaded1 = await _userManager.FindByNameAsync(email);
            if (loaded1 == null)
            {
                return false;
            }
            
            return await _userManager.CheckPasswordAsync(loaded1, password);
        }
    }</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-use-asp-net-identity-in-a-console-apps/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Make Your ASP.NET Application Pool Keep Alive</title>
		<link>https://topreviewhostingasp.net/how-to-make-your-asp-net-application-pool-keep-alive/</link>
					<comments>https://topreviewhostingasp.net/how-to-make-your-asp-net-application-pool-keep-alive/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Fri, 10 Feb 2023 06:10:16 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[application pool]]></category>
		<category><![CDATA[application pool website]]></category>
		<category><![CDATA[asp net]]></category>
		<category><![CDATA[asp net tips]]></category>
		<category><![CDATA[asp net tutorial]]></category>
		<category><![CDATA[keep alive website]]></category>
		<category><![CDATA[keep running website]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=3423</guid>

					<description><![CDATA[Somehow what you need is to have IIS keep website alive. You need to keep your ASP.NET website and application pool always running. Regardless of application pool, website, IIS web server, or the entire server restarting. Perhaps the main reasons could be that you need to initialize some code at the global asax at application start up. To fire [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Somehow what you need is to have IIS keep website alive. You need to keep your ASP.NET website and application pool always running. Regardless of application pool, website, IIS web server, or the entire server restarting.</p>



<p>Perhaps the main reasons could be that you need to initialize some code at the global asax at application start up. To fire up some global application logic. To warm up some pages. Or have an in memory timer in the ASP.NET application memory that routinely runs a schedule. What have you.</p>



<p>And you need to keep the website alive and always running, preventing the application or website from shutting down, or to turn cold because of idling or application pool recycling.</p>



<h2 class="wp-block-heading"><strong>IIS keep website alive – Solution:</strong></h2>



<p>Since the availability of IIS Application Initialization feature, keeping ASP.NET website and app pool always running is not a complicated task.</p>



<p>You need these IIS prerequisites to keep your ASP.NET website always running:</p>



<ol>
<li><a href="https://docs.microsoft.com/en-us/iis/configuration/system.webserver/applicationinitialization/" target="_blank" rel="noreferrer noopener">Application Initialization</a> Feature</li>
<li>Website or Application Preload Enabled</li>
<li>Application Pool Start Mode: AlwaysRunning</li>
</ol>



<p>So here goes…</p>



<h3 class="wp-block-heading">Application Initialization Feature</h3>



<p>Having this feature installed, gives you the ability to make IIS automatically probe your website or web application (like a visitor hitting your page) to keep it active and warm. It can also let you serve a static page (splash page) when your website is starting up.</p>



<p>The <strong>Application Initialization</strong> Feature can be installed as part of IIS features.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="876" height="636" class="wp-image-3424 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-web-server-application-initialization.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-web-server-application-initialization.png 876w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-web-server-application-initialization-300x218.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-web-server-application-initialization-768x558.png 768w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-web-server-application-initialization-50x36.png 50w" sizes="(max-width: 876px) 100vw, 876px" /></figure></div>


<h3 class="wp-block-heading">Website or Application Preload Enabled</h3>



<p>With <strong>Preload Enabled</strong> option set to true, IIS will simulate a request to ping your website or application as soon as a worker process (w3wp.exe) for your website or application is started. This will warm up your website or application. This dummy request hit will however not be logged in the IIS Log.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="438" height="544" class="wp-image-3425 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-advanced-settings-preload-enabled.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-advanced-settings-preload-enabled.png 438w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-advanced-settings-preload-enabled-242x300.png 242w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-advanced-settings-preload-enabled-40x50.png 40w" sizes="(max-width: 438px) 100vw, 438px" /></figure></div>


<h3 class="wp-block-heading">Application Pool Start Mode: AlwaysRunning</h3>



<p>Making <strong>Start Mode</strong> option AlwaysRunning will make IIS spawn a new worker process (w3wp.exe) for your website or application whenever IIS is started. Or when your application pool idle time-out and shut down occurs. Or when your application pool is recycled.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="437" height="546" class="wp-image-3426 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-advanced-settings-start-mode-alwaysrunning.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-advanced-settings-start-mode-alwaysrunning.png 437w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-advanced-settings-start-mode-alwaysrunning-240x300.png 240w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-advanced-settings-start-mode-alwaysrunning-40x50.png 40w" sizes="(max-width: 437px) 100vw, 437px" /></figure></div>


<p>With these main ingredients mentioned in place, your website is set to keep running and warm even without real visitors hitting.</p>



<h3 class="wp-block-heading">Other considerations to keep your website or application run properly while always running</h3>



<ol type="a">
<li>Application Pool Idle Time-out</li>
<li>Application Pool Recycling</li>
</ol>



<p>While achieving a constantly warm and running website or application, it does not mean that there is nothing to worry. These two options, the Idle Time-out and Recycling may cause you problems if you do not understand how it works.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="422" height="129" class="wp-image-3427 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-advanced-settings-idle-time-out.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-advanced-settings-idle-time-out.png 422w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-advanced-settings-idle-time-out-300x92.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-advanced-settings-idle-time-out-50x15.png 50w" sizes="(max-width: 422px) 100vw, 422px" /></figure></div>


<p>In consideration, you can set the Idle Time-out to 0 to disable time-out. This may sound like a logical idea to not end your application pool process since you want it always running. But if your website or application has memory leak issues, you will be in for a surprise when your memory max out due to this.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="675" height="514" class="wp-image-3429 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-recycling-settings.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-recycling-settings.png 675w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-recycling-settings-300x228.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2023/02/iis-website-application-pool-recycling-settings-50x38.png 50w" sizes="(max-width: 675px) 100vw, 675px" /></figure></div>


<p>In consideration, you can disable all recycling options here. This may also sound like you have finally found a total solution to a completely uninterruptible website or application. But memory leak is also a beast here. If your website or application memory is not well programmed or managed.</p>



<p>Hence for memory leak control, it might actually be a good idea to use these features to regularly recycle the application pool to release memory resources. However again, your codes must properly anticipate and handle these recycling interruptions. To reinitialize upon start up or save state during shut down at recycling time.</p>



<p>With all these information, you should be able to maintain a properly managed always running website or application that suits your needs.</p>



<p>Happy coding!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-make-your-asp-net-application-pool-keep-alive/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Why HostForLIFE.eu for Your ASP.NET Hosting in 2023?</title>
		<link>https://topreviewhostingasp.net/hostforlife-eu-best-asp-net-hosting-2023/</link>
					<comments>https://topreviewhostingasp.net/hostforlife-eu-best-asp-net-hosting-2023/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Tue, 10 Jan 2023 04:07:22 +0000</pubDate>
				<category><![CDATA[Hosting Review]]></category>
		<category><![CDATA[asp net]]></category>
		<category><![CDATA[asp net hosting]]></category>
		<category><![CDATA[best asp net hosting]]></category>
		<category><![CDATA[cheap asp net hosting]]></category>
		<category><![CDATA[europe asp.net hosting]]></category>
		<category><![CDATA[recommended asp net hosting]]></category>
		<category><![CDATA[reliable asp net hosting]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=3343</guid>

					<description><![CDATA[When working as a web developer, it is important to use the most updated software and tools in order to provide the best service for your clients. While there are plenty of options that you can use for ASP.NET hosting, HostForLIFE.eu hosting has emerged as one of the most beneficial options you can use. With [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>When working as a web developer, it is important to use the most updated software and tools in order to provide the best service for your clients. While there are plenty of options that you can use for ASP.NET hosting, HostForLIFE.eu hosting has emerged as one of the most beneficial options you can use. With HostForLIFE.eu hosting, web developers are able to deploy ASP.NET website easily.</p>



<h2 class="wp-block-heading">Benefits for Freelance Web Developers</h2>



<p><strong>1. Great and High Intuitive UI</strong></p>



<p>This is my favorite part about HostForLIFE.eu. I can create a variety of domains in my account for a variety of needs for my clients. I can separate users to access the dashboard, from low end client with minimal needs and high end client with more complex needs. It’s not complex, but it’s also not for a beginner who knows nothing about control panel unless he’s willing to put the time in to understand.</p>



<p><strong>2. Manage Multiple App Installs In Control Panel</strong></p>



<p>Each server you control can have a multiple different applications such as WordPress, Umbraco, Dotnetnuke, Custom PHP and nopCommerce. The benefit here is that each install is also isolated to itself for an added security layer, and you still have root access to all your applications.</p>



<p><strong>3. Website Migration Tools for Easier Website Transfers</strong></p>



<p>HostForLIFE.eu hosting makes it pretty easy to move a ASP.NET website from one hosting provider to another. The tool they provide for migration makes it awesome to move the large website files without having to slave away manually doing the work. You also don’t need to have the SFTP login credentials for the source site. This makes moving clients away from bad developers a little easier without the confrontation. </p>



<p><strong>4. Run High Quality Website Without The Complexity</strong></p>



<p>One of the things I love about HostForLIFE.eu is that it allows me to manage my ASP.NET websites without the need to be a server expert. Pricing is predictable and affordable.</p>



<p><strong>5. Simple Helpdesk System</strong></p>



<p>I really am super in love with how simple they have made the UI of this website. They have super minimal menu items and support is always a floating tab in eyesight for easy access.</p>



<p>The new trend with bad hosting companies has been to make the trail to find support so complex that you want to give up even trying to create a ticket. It’s hard to contact support team. It actually feels like an insult because when I pay a company, I expect them to make it easy for me to contact if I need assistance. I’m paying for a service, therefore, I want to be served respectfully.</p>



<h2 class="wp-block-heading">Notable Highlights of HostForLIFE.eu</h2>



<p><strong>1. Simplicity and Choice</strong></p>



<p>One of the main highlights of HostForLIFE.eu that makes it among the best ASP.NET hosting options is that it offers users with the most simplicity as well as the most choices. With HostForLIFE.eu, businesses can get support for up to unlimited applications, get support for all ASP.NET and PHP apps and get an innovative cover panel.</p>



<p><strong>2. Worry Free Experience</strong></p>



<p>Using HostForLIFE.eu provides businesses with the best web hosting experience by offering one that is worry free. Users will get 24/7 support, managed security, automated backups and 24/7 monitoring in real time.</p>



<p><strong>2. Scaled Performance</strong></p>



<p>HostForLIFE.eu also offers performance that scales as well. With this option, businesses will be able to get optimized stacks and built in CDN. They will also have access to auto healing services and ASP.NET Core ready servers as well.</p>



<h2 class="wp-block-heading">HostForLIFE.eu Also Have Managed Dedicated Server</h2>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://www.hostforlife.eu" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="1024" height="503" class="wp-image-673 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2017/07/hostforlife-home-page-1024x503.jpg" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2017/07/hostforlife-home-page-1024x503.jpg 1024w, https://topreviewhostingasp.net/wp-content/uploads/2017/07/hostforlife-home-page-300x147.jpg 300w, https://topreviewhostingasp.net/wp-content/uploads/2017/07/hostforlife-home-page-768x377.jpg 768w, https://topreviewhostingasp.net/wp-content/uploads/2017/07/hostforlife-home-page-50x25.jpg 50w, https://topreviewhostingasp.net/wp-content/uploads/2017/07/hostforlife-home-page.jpg 1336w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure></div>


<p>This managed hosting option assists many businesses unleash the full potential of their websites at all times.</p>



<p>With HostForLIFE.eu, businesses will be able to get a website that will go live within minutes. This cloud hosting platform eliminates all of the complexities of establishing a website. As a result, you can get your website operating live within a matter of a few minutes. Other hosting options usually require a day or two to go live.</p>



<p>With HostForLIFE.eu, businesses can also get their sites managed in the most professional manner. When using this option, both web designers and businesses can built and manage a website and apps with more collaboration and efficiency.</p>



<p>By using HostForLIFE.eu, businesses and web designers can use an option that will provide the fastest performance along with guaranteed security and scalability for any website they built and host.</p>



<h2 class="wp-block-heading">Don&#8217;t Worry with HostForLIFE.eu! You are in the RIGHT Hand!</h2>



<p>Whenever you construct and run a website, there is a possibility of something going wrong. As a result, businesses and web designers will often need to resolve these problems immediately. While web designers can spend time resolving any problems with a site, HostForLIFE.eu helps eliminate this hassle.</p>



<p>Since HostForLIFE.eu offers support 24 hours a day 7 days a week and 365 days a year, both businesses and web developers will be able to get any problem solved quickly and easily. With features such as the Advanced Support option, users will be able to improve the level of support they get. As a result, businesses and web developers will be able to have the tools they need to maintain a quality website.</p>



<h2 class="wp-block-heading">Best Hosting for ASP.NET</h2>



<p>Another highlight of HostForLIFE.eu and a reason to use this as your hosting option is that it will allow you to guarantee success for any website that uses ASP.NET. Many businesses and web developers often use ASP.NET in order to make and run websites. With HostForLIFE.eu, you can get the <a href="https://www.hostforlife.eu" target="_blank" rel="noreferrer noopener">most trusted hosting for your ASP.NET and also PHP website</a>.</p>



<p>If you&#8217;re not enough with their shared hosting, you can always upgrade to their VPS/dedicated hosting option. The managed hosting features include many things to help manage a website. These include advanced cashes with Breeze and CDN to provide your website with the fastest possible performance. All of these features create a more efficient web hosting experience for users.</p>



<h2 class="wp-block-heading">Features of HostForLIFE.eu</h2>



<p>HostForLIFE.eu offers both businesses and web developers a number of features that make it the preferred choice for a ASP.NET hosting platform. These features make HostForLIFE.eu stand out from other ASP.NET hosting platforms that are currently available.</p>



<p><strong>1. 24/7/365 Support</strong></p>



<p>Users get all of the help they need using the platform. They can access any assistance at any time throughout the day. With a team of highly trained experts, businesses and web deveopers will be sure to keep their websites working at their best.</p>



<p><strong>2. 30 Minute or Less Response Time</strong></p>



<p>HostForLIFE.eu offers Advanced Support which provides users with with a priority response time of 30 minutes or less.</p>



<p><strong>3. Server Customization and Configuration</strong></p>



<p>Users can have ASP.ET and other PHP custom packages deployed by using HostForLIFE.eu. The platform can also cache configurations and make changes with the configuration of any server as well.</p>



<p><strong>4. Application Level Issues</strong></p>



<p>Features such as theme troubleshooting, plug ins, and investigation of server errors can help businesses manage their databases and email add ons. These features help optimize the overall performance of a website.</p>



<h2 class="wp-block-heading">High Speed Performance</h2>



<p>HostForLIFE.eu ensures that businesses and web developers have ASP.NET websites that always come with high speed performance. Users will get a website with access to dedicated resources. This platform also offers SSD based hosting which is 3 times faster than other hosting platforms.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="746" height="401" class="wp-image-493 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2017/04/hostforlife-load-impact-response-time.jpg" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2017/04/hostforlife-load-impact-response-time.jpg 746w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/hostforlife-load-impact-response-time-300x161.jpg 300w, https://topreviewhostingasp.net/wp-content/uploads/2017/04/hostforlife-load-impact-response-time-50x27.jpg 50w" sizes="(max-width: 746px) 100vw, 746px" /></figure></div>


<p>With other features such as built in caches, <strong>ASP.NET Core ready servers</strong>, CDN and Auto healing managed cloud servers, users will ensure that their website will always work at its best using the latest technology.</p>



<h2 class="wp-block-heading">Managed Hosting and Security</h2>



<p>When it comes to hosting a website and running it, security is one of the primary concerns of both businesses and web developers. With HostForLIFE.eu, you will never have to worry about any information being compromised. That is because HostForLIFE.eu uses the most updated managed security features that are currently available.</p>



<p>Some of the features you get with HostForLIFE.eu include dedicated firewalls, 1 click free SSL installation, IP whitelisting, security patching, two factor authentication, IaaS providers and block storage. These ensure that your website will be protected from any hackers or software that can ruin your website.</p>



<h2 class="wp-block-heading">Comprehensive Management of Your Website</h2>



<p>Another one of the best things about HostForLIFE.eu is that it provides users with the most possible flexibility. You will get the most comprehensive management of your server. By using HostForLIFE.eu, users will get features such as vertical scaling of technology resources, database support, multiple versions of ASP.NET, global availability and support for all apps associated with PHP.</p>



<h2 class="wp-block-heading">Smooth Team Collaboration</h2>



<p>With smooth workflow and team collaboration, users will be able to achieve all of their goals. Some of the features included are integration of Git, WebDeploy and FTP and cloning of applications and servers. Users will also get one account for multiple teams, management of projects, staging areas for URLs and the ability to add more team members at any time. HostForLIFE.eu also allows users to transfer servers and use a migratory plug in to migrate WordPress from an old hosting site and put it into a new one for free.</p>



<h2 class="wp-block-heading">Full Control</h2>



<p>As a web developers or a business owner, it is important to have autonomy on how you want your website to be run and managed. With HostForLIFE.eu, you can take advantage of an easy to use UI that enables you to control any application or server with ease.</p>



<p>You can take advantage of options such as 1 click backup and restore, a 1 click stop app, app settings using UI and a supervised Queue manager. Users can also change the application Webroot as well.</p>



<h2 class="wp-block-heading">Great Integration</h2>



<p>A user can use one account to integrate multiple programs and add on features. This platform offers HostForLIFE.eu Bot Channels, API and application migration add on features. HostForLIFE.eu also includes SMTP add ons, email add ons using Business Email and application upgrade add ons as well. The one account feature also includes HostForLIFE.eu support add ons that users can take advantage of too.</p>



<h2 class="wp-block-heading">Stay Updated with Latest Technologies</h2>



<p>HostForLIFE.eu always allows users to keep track of their technology and stay updated on it as the same time. This platform offers 24/7 real time monitoring to ensure that your site and server are working properly. It also offers new relic integration which allows users to get insight on app performance in order to troubleshoot and identify issues with your site.</p>



<p>Lastly, HostForLIFE.eu Bot Notifications provide users with AI based assistance that provide information to help you optimize your servers and applications.</p>
<h2>Conclusion</h2>
<p>If you want to give your full attention to business growth without getting into server-related hassles, then HostForLIFE.eu hosting is the ideal choice.</p>
<p>It is the best hosting for ASP.NETthat lets you get a stress-free hosting experience and tweak your site’s performance.</p>
<p>I would blindly recommend HostForLIFE.eu Hosting for ASP.NET users because of its flexibility, reliability, and support facility.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/hostforlife-eu-best-asp-net-hosting-2023/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Use ILogger in .NET Applications to Trace Logging Output</title>
		<link>https://topreviewhostingasp.net/how-to-use-ilogger-in-net-applications-to-trace-logging-output/</link>
					<comments>https://topreviewhostingasp.net/how-to-use-ilogger-in-net-applications-to-trace-logging-output/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Thu, 22 Dec 2022 06:38:28 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net]]></category>
		<category><![CDATA[asp net core tips]]></category>
		<category><![CDATA[asp net tips]]></category>
		<category><![CDATA[asp net tutorial]]></category>
		<category><![CDATA[ilogger asp net core]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=3328</guid>

					<description><![CDATA[.NET’s greatest strength is its long history of supporting developers through each industry paradigm shift, but just because there’s a new way of doing things doesn’t mean the established method goes away. It’s also a source of confusion and frustration for many. Developers spend time trying to merge the past with the present while also [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>.NET’s greatest strength is its long history of supporting developers through each industry paradigm shift, but just because there’s a new way of doing things doesn’t mean the established method goes away. It’s also a source of confusion and frustration for many. Developers spend time trying to merge the past with the present while also thinking about the future. One of the problem domains folks have to think about is some form of tracing in their apps.</p>



<p>This post will show how to take one of the oldest tracing methods, <code>System.Diagnostics.Trace</code>, and adapt your newer .NET applications (.NET 5+) to take advantage of the messages some of your older dependencies may be emitting.</p>



<h2 class="wp-block-heading">What Is System.Diagnostics.Trace?</h2>



<p>In the early days of systems development, you typically had very simple architectures with few running processes. Traces allow for publishing specific messages during the execution of your application that you can scan over later to glean information about a running process at a particular time. Developers will put their messages into four general categories:</p>



<ul>
<li><strong>Critical</strong>: Serious failure that likely causes immediate loss of information or user functionality.</li>
<li><strong>Error:</strong>: An unexpected failure in a particular sub-system that may result in a loss of user functionality, but it is otherwise recoverable.</li>
<li><strong>Warning:</strong> An unexpected situation, but standard processing can continue.</li>
<li><strong>Information</strong>: Messages that may be helpful when diagnosing a system, but otherwise are there for developers to learn more at their convenience.</li>
</ul>



<p>You can find traces in many .NET Dependencies, but messages are usually are not surfaced until you register a <code>Listener</code>. A listener redirects messages to a destination, whether a log file, the event log in Windows, the console output, or a third-party repository.</p>



<p>If you’re reading this post, you’re likely wondering: “How do I get my traces to show up through my <code>ILogger</code> configuration?” As your <code>ILogger</code> setup likely also has the configuration for logging targets like files, event logs, and third-party services. Nobody likes doing things twice, especially developers like you.</p>



<p>Well, let’s see how.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://www.asphostportal.com" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="300" height="271" class="wp-image-2584 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01-50x45.png 50w" sizes="(max-width: 300px) 100vw, 300px" /></a></figure></div>


<h2 class="wp-block-heading">Passing Trace Messages To ILogger</h2>



<p>Our goal is to pass <code>Trace</code> messages directly to an <code>ILogger</code> implementation, piggy-backing off our application’s configuration. Most importantly, the approach would allow us to see into older dependencies that may still be utilizing <code>System.Diagnostics.Trace</code> calls.</p>



<p>Our first step in the process is to write a <code>Listener</code>, which we’ll call <code>LoggerTraceListener</code>.</p>



<pre class="wp-block-code"><code>public class LoggerTraceListener : TraceListener
{
    private readonly ILoggerFactory _loggerFactory;
    private readonly ILogger _defaultLogger;
    private readonly ConcurrentDictionary&lt;string, ILogger&gt; _loggers = new();
    private readonly StringBuilder _builder = new();

    public LoggerTraceListener(ILoggerFactory loggerFactory)
    {
        _loggerFactory = loggerFactory;
        _defaultLogger = loggerFactory.CreateLogger(nameof(LoggerTraceListener));
    }

    public override void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, string? message)
    {
        var logger = _loggers.GetOrAdd(
            source,
            static (s, factory) =&gt; factory.CreateLogger(s),
            _loggerFactory);
        
        logger.Log(MapLevel(eventType), message);
    }

    public override void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, string? format,
        params object?[]? args)
    {
        var logger = _loggers.GetOrAdd(
            source,
            static (s, factory) =&gt; factory.CreateLogger(s),
            _loggerFactory);
        
        logger.Log(MapLevel(eventType), format, args ?? Array.Empty&lt;object&gt;());
    }

    public override void Write(string? message)
    {
        _builder.Append(message);
    }

    public override void WriteLine(string? message)
    {
        _builder.AppendLine(message);
        _defaultLogger.LogInformation(_builder.ToString());
        _builder.Clear();
    }

    private LogLevel MapLevel(TraceEventType eventType) =&gt; eventType switch
    {
        TraceEventType.Verbose =&gt; LogLevel.Debug,
        TraceEventType.Information =&gt; LogLevel.Information,
        TraceEventType.Critical =&gt; LogLevel.Critical,
        TraceEventType.Error =&gt; LogLevel.Error,
        TraceEventType.Warning =&gt; LogLevel.Warning,
        _ =&gt; LogLevel.Trace
    };
}</code></pre>



<p>Note that the <code>LoggerTraceListener</code> takes a dependency on an <code>ILoggerFactory</code>, which will help us preserve the source of our messages when we log with our <code>ILogger</code> implementation.</p>



<p>Now, let’s make use of our newly created listener. Next, assuming you’re working in an ASP.NET Core application, we need to register our listener with the <code>System.Diagnostics.Trace.Listeners</code> collection.</p>



<pre class="wp-block-code"><code>using System.Diagnostics;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// get logger factory and add listener
var factory = app.Services.GetRequiredService&lt;ILoggerFactory&gt;();
Trace.Listeners.Add(new LoggerTraceListener(factory));</code></pre>



<p>Great! Now we can start getting traces in the output of our running application, assuming we have the console logger enabled. Finally, Let’s add some trace calls to an endpoint to see it all in action.</p>



<pre class="wp-block-code"><code>app.MapGet("/", async () =&gt;
{
    Trace.TraceInformation("Cool Beans!");
    Trace.TraceWarning("Fudge!");
    Trace.TraceError("F#$@!");
    
    return "Hello World!";
});</code></pre>



<p>Let’s take a look at the run output.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="354" class="wp-image-3333 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2022/12/lumberjack.jpg" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2022/12/lumberjack.jpg 720w, https://topreviewhostingasp.net/wp-content/uploads/2022/12/lumberjack-300x148.jpg 300w, https://topreviewhostingasp.net/wp-content/uploads/2022/12/lumberjack-50x25.jpg 50w" sizes="(max-width: 720px) 100vw, 720px" /></figure></div>


<p>Neat! Now we can see our traces alongside all of our logging calls. But wait, there’s more! Since we are using the <code>ILogger</code> interface, we can also use the configuration options to limit what trace output gets passed to our logger. For example, in the <code>appSettings.json</code>, we can choose the level of information we want to log.</p>



<p><strong>Note: <code>Lumberjack</code> is the assembly from which we emit our traces.</strong></p>



<pre class="wp-block-code"><code>{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Lumberjack" : "Warning"
    }
  },
  "AllowedHosts": "*"
}</code></pre>



<p>Let’s make sure it work.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="414" class="wp-image-3335 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2022/12/lumberjack-2-1.jpg" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2022/12/lumberjack-2-1.jpg 720w, https://topreviewhostingasp.net/wp-content/uploads/2022/12/lumberjack-2-1-300x173.jpg 300w, https://topreviewhostingasp.net/wp-content/uploads/2022/12/lumberjack-2-1-50x29.jpg 50w" sizes="(max-width: 720px) 100vw, 720px" /></figure></div>


<p>Great!</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>As modern software development improves its techniques around tracing and observability, there will be a significant legacy codebase still heavily using <code>System.Diagnostics.Trace</code>. This post shows a method in which we can continue building modern applications with the latest and greatest tech while still taking advantage of the messages emitted by previous developers. I hope you found this post helpful, and thanks again for reading.</p>



<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-use-ilogger-in-net-applications-to-trace-logging-output/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Solve Refresh Tokens in ASP.NET Core Web Api</title>
		<link>https://topreviewhostingasp.net/how-to-solve-refresh-tokens-in-asp-net-core-web-api/</link>
					<comments>https://topreviewhostingasp.net/how-to-solve-refresh-tokens-in-asp-net-core-web-api/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Fri, 30 Sep 2022 04:56:49 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net]]></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 core web api]]></category>
		<category><![CDATA[asp net tips]]></category>
		<category><![CDATA[asp net tutorial]]></category>
		<category><![CDATA[refresh tokens asp net core]]></category>
		<category><![CDATA[solve asp net core api]]></category>
		<category><![CDATA[solve jwt tokens]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=3228</guid>

					<description><![CDATA[One thing that comes to mind when using access tokens to secure a web api is what do you do when the token expires? Do you ask the user for credentials again? That’s not really a good option. This blog post is about using refresh tokens to solve this problem. Specifically in ASP.NET Core Web [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>One thing that comes to mind when using access tokens to secure a web api is what do you do when the token expires?</p>



<p>Do you ask the user for credentials again? That’s not really a good option.</p>



<p>This blog post is about using refresh tokens to solve this problem. Specifically in ASP.NET Core Web Apis with JWT tokens.</p>



<p>First, is this really a big deal? Why don’t we just set a long expiration date in the access tokens? For example, a month or even a year?</p>



<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://www.asphostportal.com" target="_blank" rel="noopener"><img loading="lazy" decoding="async" width="300" height="271" class="wp-image-2584 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01.png" alt="" srcset="https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01.png 300w, https://topreviewhostingasp.net/wp-content/uploads/2018/11/ahp-banner-aspnet-01-50x45.png 50w" sizes="(max-width: 300px) 100vw, 300px" /></a></figure>
</div>



<p>Because if we do that and someone manages to get hold of that token they can use it for a month, or a year. Even if you change your password.</p>



<p>That’s because a server will trust a token if it’s signature is valid, and the only way to invalidate it is to change the key that was used to sign it, and that has the consequence of invalidating everyone else’s tokens.</p>



<p>Not really an option then. That leads us to the idea of using refresh tokens.</p>



<p>How does a refresh token work then?</p>



<p>Imagine that when you get an access token you also get another one-time-use token: the refresh token. The app stores the refresh token and leaves it alone.</p>



<p>Every time your app sends a request to the server it sends the access token in it (<code>Authorization: Bearer TokenGoesHere</code>) so that the server knows who you are. There will come a time where the token will expire and the server will let you know of this somehow.</p>



<p>When this happens your app sends the expired token and the refresh token and gets back a new token and refresh token. Rinse, repeat.</p>



<p>If something fishy happens the refresh token can be revoked which means that when the app tries to use it to get a new access token, that request will be rejected and the user will have to enter credentials to be able to log in again.</p>



<p>To make this last point clear, imagine that the app stores the location (e.g. Dublin, Ireland) of the request when a refresh token is created. If user can access this information, and if there’s some login from a place that the user doesn’t recognize, the user can revoke the refresh token so that when the access token expires whoever is using it won’t be able to continue to use the app. This is why it’s probably a good idea to have the access tokens be short lived (i.e be valid for a couple of minutes).</p>



<p>To use refresh tokens we need to be able to do:</p>



<ul>
<li>Create access tokens (we will use JWT here)</li>
<li>Generate, save, retrieve and revoke refresh tokens (server-side)</li>
<li>Exchange an expired JWT token and refresh token for a new JWT token and refresh token (i.e. refresh a JWT token)</li>
<li>Use ASP.NET authentication middleware to authenticate a user with JWT tokens</li>
<li>Have a way to signal that the access token expired to the app (optional)</li>
<li>When the token expires have the client transparently acquire a new token</li>
</ul>



<p>If you need information on these topics individually, continue on.</p>



<h2 class="wp-block-heading" id="create-jwt-access-tokens">Create JWT Access Tokens</h2>



<p>First you need to add the <code>System.IdentityModel.Tokens.Jwt</code> package:</p>



<pre class="wp-block-code"><code>$ dotnet add package System.IdentityModel.Tokens.Jwt
</code></pre>



<p>To create a new JWT token:</p>



<pre class="wp-block-code"><code>private string GenerateToken(IEnumerable&lt;Claim&gt; claims)
{
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("the server key used to sign the JWT token is here, use more than 16 chars"));

    var jwt = new JwtSecurityToken(issuer: "Blinkingcaret",
        audience: "Everyone",
        claims: claims, //the user's claims, for example new Claim[] { new Claim(ClaimTypes.Name, "The username"), //... 
        notBefore: DateTime.UtcNow,
        expires: DateTime.UtcNow.AddMinutes(5),
        signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
    );    

    return new JwtSecurityTokenHandler().WriteToken(jwt); //the method is called WriteToken but returns a string
}</code></pre>



<p>Here we are creating a new jwt token with an expiration date of 5 minutes signed using HmacSha256.</p>



<h2 class="wp-block-heading" id="generate-save-retrieve-and-revoke-refresh-tokens">Generate, save, retrieve and revoke refresh tokens</h2>



<p>The refresh tokens must be unique and it shouldn’t be possible (or it must be very hard) to guess them.</p>



<p>It might seem that a simple GUID satisfies this criteria. Unfortunately the process of generating <a href="https://blogs.msdn.microsoft.com/oldnewthing/20120523-00/?p=7553">GUIDs is not random</a>. That means that given a few guids you can easily guess the next one.</p>



<p>Thankfully, there’s a secure random number generator in ASP.NET Core that we can use to generate a string that is unique and even given a few of them it’s very hard to predict how the next one will be:</p>



<pre class="wp-block-code"><code>using System.Security.Cryptography;

//...

public string GenerateRefreshToken()
{
    var randomNumber = new byte[32];
    using (var rng = RandomNumberGenerator.Create()){
        rng.GetBytes(randomNumber);
        return Convert.ToBase64String(randomNumber);
    }
}</code></pre>



<p>Here we are generating a 32 byte long random number and converting it to base64 so that we can use it as a string. There are no guidelines regarding the length other than it should lead to an unique and hard to guess token. I picked 32 but even 16 should be ok.</p>



<p>We will need to generate refresh tokens when we first generate a JWT token and when we “refresh” an expired token.</p>



<p>Every time we generate a new refresh token we should save in a way that it’s linked to the user for which the access token was issued.</p>



<p>The simplest version of this is just to have an extra column for the refresh token in the user’s table. This has the consequence of only allowing the user to be logged-in in one location (there’s only 1 refresh token valid per user at a time).</p>



<p>Alternatively, you can maintain several refresh tokens per user and save the geographical location, time, etc from the request that originated them so that you can provide the user with activity reports.</p>



<p>Also, it is probably a good idea to make the refresh tokens expire, for example after a few days (you’d have to save an expiration date together with the refresh token).</p>



<p>One thing you must not forget to do is to remove a refresh token when it is used in a refresh operation so that it cannot be used more than once.</p>



<h2 class="wp-block-heading" id="exchange-an-expired-jwt-and-refresh-token-for-a-new-jwt-token-and-refresh-token-i-e-refresh-a-jwt-token-">Exchange an expired JWT and refresh token for a new JWT token and refresh token (i.e. refresh a JWT token)</h2>



<p>To get a new access token from an expired one we need to be able to access the claims inside the token even though the token is expired.</p>



<p>When you use the ASP.NET Core authentication middleware for authenticating the user using JWT it will return a 401 response to an expired token.</p>



<p>We need to create a controller action that allows anonymous users and that takes the JWT and refresh tokens.</p>



<p>In that controller action we need to manually validate the expired access token (there’s an option to ignore the token lifetime) and extract all the information about the user contained in it.</p>



<p>We can then use the user information to retrieve the stored refresh token. We can then compare the stored refresh token with the one that was sent in the request.</p>



<p>If all is good we create new JWT and refresh tokens, save the new refresh token, discard the old and send the new JWT and refresh tokens to the client.</p>



<p>Here’s how you can retrieve the user information in the form of a <code>ClaimsPrincipal</code> from the expired JWT token:</p>



<pre class="wp-block-code"><code>private ClaimsPrincipal GetPrincipalFromExpiredToken(string token)
{
    var tokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = false, //you might want to validate the audience and issuer depending on your use case
        ValidateIssuer = false,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("the server key used to sign the JWT token is here, use more than 16 chars")),
        ValidateLifetime = false //here we are saying that we don't care about the token's expiration date
    };

    var tokenHandler = new JwtSecurityTokenHandler();
    SecurityToken securityToken;
    var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out securityToken);
    var jwtSecurityToken = securityToken as JwtSecurityToken;
    if (jwtSecurityToken == null || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
        throw new SecurityTokenException("Invalid token");

    return principal;
}</code></pre>



<p>The noteworthy parts in the above snippet are that we are using <code>ValidateLifeTime = false</code> in the <code>TokenValidationParameters</code> so that the expired token is considered valid. Also, we are checking that the algorithm used to sign the token is the one we expect (HmacSha256 in this example).</p>



<p>The reason for this is that in theory someone could create a JWT token and <a href="https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/">set the signing algorithm to “none”</a>. The JWT token would be valid (even if unsigned). This way using a valid refresh token it would be possible to exchange a fake token for a real JWT token.</p>



<p>Now we just need the controller action (it should be a POST since it has side effects and also the tokens are too long for query string parameters):</p>



<pre class="wp-block-code"><code>[HttpPost]
public IActionResult Refresh(string token, string refreshToken)
{                   
    var principal = GetPrincipalFromExpiredToken(token);
    var username = principal.Identity.Name;
    var savedRefreshToken = GetRefreshToken(username); //retrieve the refresh token from a data store
    if (savedRefreshToken != refreshToken)
        throw new SecurityTokenException("Invalid refresh token");

    var newJwtToken = GenerateToken(principal.Claims);
    var newRefreshToken = GenerateRefreshToken();
    DeleteRefreshToken(username, refreshToken);
    SaveRefreshToken(username, newRefreshToken);

    return new ObjectResult(new {
        token = newJwtToken,
        refreshToken = newRefreshToken
    });
}</code></pre>



<p>There are a few assumptions in the snippet above. There’s the retrieving, saving and deleting that I’ve omitted, and also there’s the assumption that there’s only one refresh token per user which is the simplest scenario.</p>



<h2 class="wp-block-heading" id="use-the-asp-net-core-authentication-middleware-to-authenticate-a-user-using-a-jwt-token">Use the ASP.NET Core authentication middleware to authenticate a user using a JWT token</h2>



<p>We need to configure ASP.NET Core’s middleware pipeline so that if a request comes in with a valid <code>Authorization: Bearer JWT_TOKEN</code> header the user is &#8220;signed in&#8221;.</p>



<p>After version 2.0 of ASP.NET Core we add a single authentication middleware to the pipeline and we configure it in <code>Startup.cs</code>‘ <code>ConfigureServices</code>:</p>



<pre class="wp-block-code"><code>public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    //...

    services.AddAuthentication(options =&gt;
    {
        options.DefaultAuthenticateScheme = "bearer";
        options.DefaultChallengeScheme = "bearer";
    }).AddJwtBearer("bearer", options =&gt;
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = false,
            ValidateIssuer = false,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("the server key used to sign the JWT token is here, use more than 16 chars")),
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero //the default for this setting is 5 minutes
        };
        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =&gt;
            {
                if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                {
                    context.Response.Headers.Add("Token-Expired", "true");
                }
                return Task.CompletedTask;
            }
        };
    });
}</code></pre>



<p>Of note in the snippet above is the handling of the <code>OnAuthenticationFailed</code> event. It will add a <code>Token-Expired</code> header to the response when a request comes in with an expired token. The client can use this information to decide to use the refresh token. However, we can just have the client try to use the refresh token when it gets a 401 response. We’ll rely on the <code>Token-Expired</code> header being in the response for the rest of this blog post.</p>



<p>Now we just need to add the <code>Authentication</code> middleware to the pipeline:</p>



<pre class="wp-block-code"><code>public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseAuthentication();
    //...</code></pre>



<h2 class="wp-block-heading" id="the-client">The client</h2>



<p>The goal here is to build an api client that can realize when a token has expired and take the appropriate actions to get a new token, and do all of this transparently.</p>



<p>When a request fails because of an expired access token, a new request should be sent to a refresh endpoint with the access and refresh tokens. After that request completes and the client gets the new tokens, the original request should be repeated.</p>



<p>The implementation for this will depend on which type of client you are using. Here we will describe a possible JavaScript client. We’ll be relying on the response to a request with an expired token having a header named <code>"Token-Expired"</code>. We’ll be using <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"><code>fetch</code></a> to perform requests to the web api.</p>



<pre class="wp-block-code"><code>async function fetchWithCredentials(url, options) {
    var jwtToken = getJwtToken();
    options = options || {};
    options.headers = options.headers || {};
    options.headers['Authorization'] = 'Bearer ' + jwtToken;
    var response = await fetch(url, options);
    if (response.ok) { //all is good, return the response
        return response;
    }

    if (response.status === 401 &amp;&amp; response.headers.has('Token-Expired')) {
        var refreshToken = getRefreshToken();

        var refreshResponse = await refresh(jwtToken, refreshToken);
        if (!refreshResponse.ok) {
            return response; //failed to refresh so return original 401 response
        }
        var jsonRefreshResponse = await refreshResponse.json(); //read the json with the new tokens

        saveJwtToken(jsonRefreshResponse.token);
        saveRefreshToken(jsonRefreshResponse.refreshToken);
        return await fetchWithCredentials(url, options); //repeat the original request
    } else { //status is not 401 and/or there's no Token-Expired header
        return response; //return the original 401 response
    }
}</code></pre>



<p>In the snippet above there’s <code>getJwtToken</code>, <code>getRefreshToken</code>, <code>saveJwtToken</code> and <code>saveRefreshToken</code>. In a browser these would use the browser’s <code>localStorage</code> to save and retrieve the tokens, for example:</p>



<pre class="wp-block-code"><code>function getJwtToken() {
    return localStorage.getItem('token');
}

function getRefreshToken() {
    return localStorage.getItem('refreshToken');
}

function saveJwtToken(token) {
    localStorage.setItem('token', token);
}

function saveRefreshToken(refreshToken) {
    localStorage.setItem('refreshToken', refreshToken);
}</code></pre>



<p>There also the <code>refresh</code> function. This function performs a POST request to the api endpoint for refreshing tokens, for example if that endpoint is at <code>/token/refresh</code>:</p>



<pre class="wp-block-code"><code>async function refresh(jwtToken, refreshToken) {
    return fetch('token/refresh', {
        method: 'POST',
        body: `token=${encodeURIComponent(jwtToken)}&amp;refreshToken=${encodeURIComponent(getRefreshToken())}`,
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    });
}</code></pre>



<p>This is how using this client would look like if you were trying it out in the chrome developer tools console:</p>



<figure class="wp-block-image size-large"><img decoding="async" class="wp-image-3229" src="https://topreviewhostingasp.net/wp-content/uploads/2022/09/Error-In-Console.jpeg" alt="" /></figure>



<figure class="wp-block-image size-large"><img decoding="async" class="wp-image-3230" src="https://topreviewhostingasp.net/wp-content/uploads/2022/09/401.jpeg" alt="" /></figure>



<p>One thing to note here is the 401 that shows up in red in the console. That happens when the request fails because of the expired token.</p>



<p>If seeing the “error” (error in quotes because it’s a valid status code and appropriate in this case) is something you’d like to avoid, you can access the token’s expiration date in JavaScript and refresh it before it expires.</p>



<p>A JWT token has 3 parts separated by a a “.”. The second part contains the user’s claims, and in there there’s a claim named <code>exp</code> which contains the unix time stamp of when the token expires. This is how you can get a JavaScript date object with the expiration date for a JWT token:</p>



<pre class="wp-block-code"><code>var claims = JSON.parse(atob(token.split('.')[1]));
var expirationDate = new Date(claims.exp*1000); //unix timestamp is in seconds, javascript in milliseconds</code></pre>



<p>Checking the expiration date feels convoluted so I don’t recommend doing it (also dealing with timezones is probably a problem). I decided to mention this because it’s something that is interesting to know and that makes it very clear that what you put in a JWT token is not secret, it just can’t be tampered with without making the token invalid.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/how-to-solve-refresh-tokens-in-asp-net-core-web-api/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The Difference Between Middleware and Filters Power in ASP.NET Core</title>
		<link>https://topreviewhostingasp.net/the-difference-between-middleware-and-filters-power-in-asp-net-core/</link>
					<comments>https://topreviewhostingasp.net/the-difference-between-middleware-and-filters-power-in-asp-net-core/#respond</comments>
		
		<dc:creator><![CDATA[Jacques Hunt]]></dc:creator>
		<pubDate>Mon, 29 Aug 2022 04:23:38 +0000</pubDate>
				<category><![CDATA[Hosting Tips]]></category>
		<category><![CDATA[asp net]]></category>
		<category><![CDATA[asp net core]]></category>
		<category><![CDATA[asp net core pipelines]]></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[filter power asp net core]]></category>
		<category><![CDATA[middleware asp net core]]></category>
		<guid isPermaLink="false">https://topreviewhostingasp.net/?p=3149</guid>

					<description><![CDATA[In ASP.NET core, Middleware and Filters are two concepts which are very useful &#38; powerful but often confuses also on which one to choose. Middleware and Filters serves similar purpose and both can be used to achieve the common tasks like exception handling, localizations, authentications etc… but both has certain difference in a way it [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p id="viewer-foo">In ASP.NET core, Middleware and Filters are two concepts which are very useful &amp; powerful but often confuses also on which one to choose.</p>



<p id="viewer-cf440">Middleware and Filters serves similar purpose and both can be used to achieve the common tasks like exception handling, localizations, authentications etc… but both has certain difference in a way it works with the pipeline.</p>



<p id="viewer-30dms">Lets understand the difference and use of Middleware and Filters through an example of Exception Handling.</p>



<h2 class="wp-block-heading" id="viewer-74i9f">M<strong>iddleware</strong></h2>



<p id="viewer-a01dg">It allows in the pipeline to handle requests and responses Where you can choose if the component “<strong>is to pass the request to the next component in the pipeline</strong>” or “<strong>can perform work before and after the next component in the pipeline</strong>”. i.e. Perform request validation, localization, exception handling or logging each request and response etc.</p>



<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" class="wp-image-3150 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2022/08/midlleware.jpeg" alt="" /></figure>
</div>



<h2 class="wp-block-heading" id="viewer-2j2dp">F<strong>ilters</strong></h2>



<p id="viewer-15b9d">It run within the <em>ASP.NET Core action invocation pipeline and </em>allows to perform certain operation before or after specific stages in the request processing pipeline. i.e. Perform authentication or authorization to validate requested action processing.</p>



<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" class="wp-image-3151 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2022/08/filters.jpeg" alt="" /></figure>
</div>



<p id="viewer-dnb4j">Now lets understand it with the example of Exception Handling generically using both the way.</p>



<p id="viewer-2hm9g">Scenario: Handle all unhandled exception in code to safeguard the crucial information about code to be delivered to the end user.</p>



<h3 class="wp-block-heading" id="viewer-d5c9l">1. Using Middleware.</h3>



<p id="viewer-puir">Here we try to handle all uncaught exception through out the application through a middleware we create. Middleware is a normal class so you don’t have to inherit any interface/specific class but your class must have the method called Invoke “public async Task Invoke(HttpContext context)”.</p>



<pre class="wp-block-code"><code>using Microsoft.AspNetCore.Http;
using System;
using System.Net;
using System.Threading.Tasks;
namespace CoreWebAPIDemo.Middleware
{
    public class ExceptionHandlingMiddleware
    {
        private readonly RequestDelegate _requestDelegate;
        public ExceptionHandlingMiddleware(RequestDelegate 
                                                requestDelegate)
        {
            _requestDelegate = requestDelegate;
        }
        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _requestDelegate(context);
            }
            catch (Exception ex)
            {
                await HandleException(context, ex);
            }
        }
        private Task HandleException(HttpContext context, Exception ex)
        {
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = 
                                (int)HttpStatusCode.InternalServerError;
            return context.Response.WriteAsync(ex.Message);
        }
    }
}</code></pre>



<p>In above code here I have RequestDelegate dependency resolving code to handle the http request because my requirement to catch the unhandled exception in the pipeline . Now lets add an extension method for IApplicationBuilder to simplify the call for this middleware.</p>



<pre class="wp-block-code"><code>using Microsoft.AspNetCore.Builder;
namespace CoreWebAPIDemo.Middleware
{
    public static class ExceptionHandlerMiddlewareExtension
    {
        public static IApplicationBuilder UseExceptionHandlerMiddleware(
            this IApplicationBuilder builder)
        {
            return builder.UseMiddleware&lt;ExceptionHandlingMiddleware&gt;();
        }
    }
}</code></pre>



<p>Our Middleware to catch the uncaught exception is ready and now we need to register it to request pipeline which will be from S<strong>tartup.Configure </strong>method. Here we have to be very careful as the pipeline order is driven through the order of middleware services you add. In this we need to catch the exception while processing the request hence I’ll be adding this middleware at the end just before the UseEndpoints middleware call.</p>



<pre class="wp-block-code"><code>public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpsRedirection();      
    app.UseRouting();      
    app.UseStaticFiles();      
    app.UseCors("AllowAll");      
    app.UseExceptionHandlerMiddleware();      
    app.UseEndpoints(endpoints =&gt;
            {
                endpoints.MapControllers();
            });
}</code></pre>



<p>and finally to test the code, lets create a control which will throw the exception.</p>



<pre class="wp-block-code"><code>using Microsoft.AspNetCore.Mvc;
using System;
namespace CoreWebAPIDemo.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class HomeController : ControllerBase
    {
        [HttpGet]
        public IActionResult Index(int value)
        {
            if (value == 1)
                return Ok("I'm Happy");
            else
                throw new Exception("I didn't like your number");
        }
    }
}</code></pre>



<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" class="wp-image-3152 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2022/08/localhost.jpeg" alt="" /></figure>
</div>



<p>output would be:</p>



<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" class="wp-image-3153 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2022/08/localhost_2.jpeg" alt="" /></figure>
</div>



<p id="viewer-1veob">Now lets do the exception handling through action filter.</p>



<h2 class="wp-block-heading" id="viewer-2br44">2. Using Filter.</h2>



<p id="viewer-dotra">Here we will create a action filter which inherits IActionFilter.</p>



<pre class="wp-block-code"><code>using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Net;
namespace CoreWebAPIDemo.Middleware
{
    public class ExceptionHandlerFilter : Attribute, IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext context) 
        { }
        public void OnActionExecuted(ActionExecutedContext context)
        {
            if (context.Exception is Exception exception)
            {
                context.Result = new ObjectResult(exception.Message)
                {
                    StatusCode = (int)HttpStatusCode.InternalServerError,
                };
                context.ExceptionHandled = true;
            }
        }
    }
}</code></pre>



<p id="viewer-492kg">In this case, we are adding code to handle exception OnActionExecute method which will get executed after the action is executed.</p>



<p id="viewer-90o06">Now we need to register it through <strong>Startup.ConfigureServices</strong> method if we want to apply it forcefully to all the controller’s action execution and here we can add this anywhere in the method without worrying about the order.</p>



<pre class="wp-block-code"><code>services.AddControllers(options =&gt; options.Filters.Add(new ExceptionHandlerFilter()));</code></pre>



<p id="viewer-9ol8m">Or we can also restrict it to a specific controller or action method and this is one big advantage over using Middleware concept to handle exceptions like in this scenario. Also when we reach here our MVC context is fully ready like model binding and all is done and available with the context.</p>



<p id="viewer-47ph0">And this is the reason, I have also inherited <strong>Attribute </strong>class while creating ExceptionHandlerFilter. Now here is the code to use it with the specific controller only.</p>



<pre class="wp-block-code"><code>using CoreWebAPIDemo.Middleware;
using Microsoft.AspNetCore.Mvc;
using System;namespace CoreWebAPIDemo.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    [ExceptionHandlerFilter]
    public class HomeController : ControllerBase
    {
        [HttpGet]
        public IActionResult Index(int value)
        {
            if (value == 1)
                return Ok("I'm Happy");
            else
                throw new Exception("I didn't like your number");
        }
    }
}</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>Note: Don’t forget to comment the earlier middleware code for registering “<strong>app.UseExceptionHandlerMiddleware();” </strong>in case if you are in same project like me while testing.</em></p>
</blockquote>



<h2 class="wp-block-heading">Other Point</h2>



<p id="viewer-c4n11">ASP.NET core also provides predefined middleware for exception handing which you can use to control the information flowing to the use in case of uncaught exception or error and you can achieve that by doing this:</p>



<p id="viewer-2vgu0">1. Create an ErrorController and two action method as below to handle development and production scenario.</p>



<pre class="wp-block-code"><code>using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
namespace CoreWebAPIDemo.Controllers
{[ApiController]
    [Route("api/[controller]")]
    public class ErrorController : ControllerBase
    {
        /// &lt;summary&gt;
        /// The preceding Error action sends an RFC 7807-compliant payload 
            to the client.
        /// &lt;/summary&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        [Route("/error")]
        public IActionResult Error() =&gt; Problem("Oops there is a problem. 
        Excuse me and smile!");
        [Route("/error-local-development")]
        public IActionResult ErrorLocalDevelopment(
        [FromServices] IWebHostEnvironment webHostEnvironment)
        {
            if (webHostEnvironment.EnvironmentName != "Development")
            {
                throw new InvalidOperationException("Ugggh! This is not 
                for Production, go away.");
            }
            var context = 
                 HttpContext.Features.Get&lt;IExceptionHandlerFeature&gt;();
            return Problem(
                detail: context.Error.StackTrace,
                title: context.Error.Message);
        }
    }
}</code></pre>



<p>2. Enable ASP.NET Core predefined ExceptionHandler middleware from <strong>Startup.Configure</strong> method.</p>



<pre class="wp-block-code"><code>public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
     if (env.IsDevelopment())
     {
          app.UseExceptionHandler("/error-local-development");
     }
     else
     {
          app.UseExceptionHandler("/error");
     }     
    app.UseHttpsRedirection();     
    app.UseRouting();     
    app.UseStaticFiles();     
    app.UseCors("AllowAll");     
    app.UseEndpoints(endpoints =&gt;
            {
                endpoints.MapControllers();
            });
}</code></pre>



<h2 class="wp-block-heading" id="viewer-d7u79">Middleware vs Filters</h2>



<p id="viewer-8hkth">The first step is to consider why you would choose to use middleware over filters, or vice versa. Both are designed to handle cross-cutting concerns of your application and both are used in a &#8216;pipeline&#8217;, so in some cases you could choose either successfully.</p>



<p id="viewer-42ff1">The main difference between them is their scope. Filters are a part of MVC, so they are scoped entirely to the MVC middleware. Middleware only has access to the HttpContext and anything added by preceding middleware. In contrast, filters have access to the wider MVC context, so can access routing data and model binding information for example.</p>



<p id="viewer-5d6js">Generally speaking, if you have a cross cutting concern that is independent of MVC then using middleware makes sense, if your cross cutting concern relies on MVC concepts, or must run midway through the MVC pipeline, then filters make sense.</p>



<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" class="wp-image-3154 aligncenter" src="https://topreviewhostingasp.net/wp-content/uploads/2022/08/middleware_2.jpeg" alt="" /></figure>
</div>



<p id="viewer-2o29s">First, you have some middleware that already does what you want, but you now need the behaviour to occur midway through the MVC middleware. You could rewrite your middleware as a filter, but it would be nicer to just be able to plug it in as-is. This is especially true if you are using a piece of third-party middleware and you don&#8217;t have access to the source code.</p>



<p id="viewer-efnt6">Second, you have functionality that needs to logically run as <em>both</em> middleware and a filter. In that case you can just have the one implementation that is used in both places.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://topreviewhostingasp.net/the-difference-between-middleware-and-filters-power-in-asp-net-core/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
