Tuesday, 5 June 2018

URL rewrite & redirect in .net web apps.

URL rewrite module. Example for default HTTP to HTTPS redirection. Corresponding XML must be placed in web.config as a child of <system.webServer>


    <rewrite>
      <rules>
        <clear />
        <rule name="Redirect to https" stopProcessing="true">
          <match url="(.*)" />
          <conditions>
            <add input="{HTTPS}" pattern="off" ignoreCase="true" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" 
                redirectType="Permanent" appendQueryString="false" />
        </rule>
      </rules>
    </rewrite>

Http Redirect module. Example http://mysite/login to http://anothersite.com/login Corresponding XML must be placed in web.config as a first child of <configuration>.


  <location path="login">
    <system.webServer>
      <httpRedirect enabled="true" destination="http://anothersite.com/login"
                httpResponseStatus="Permanent" />
    </system.webServer>
  </location>

Thursday, 19 April 2018

dotPeek. Compiler-Generated Code


What if you want to see Compiler-Generatied Code in dotPeek .net decompiler tool to be able analyse compiled code of generators & async/await things or see other optimizations. It's pretty simple you just need to click on the icon in the toolbar, see image

more information can be found here

Wednesday, 18 April 2018

SSL certificate update on sslforfree.com under custom circumstances

What we have:

  • There is legacy site developed with asp.net mvc and only published site is available (no CI, no sources)
  • Old sertificate is expired
  • We don't have access to DNS settings for DNS manual verification
  • According to site manual verification we need place key file inside site folder /.well-known/acme-challenge (validating URL is http://yoursite.com/.well-known/acme-challenge/{hash})
  • Routing module in the asp.net application tries to match your validation URL for further process but fails cause it can't treat that folder as static folder and tries to find and create controller. For success request of this validation rule corresponding folder must be ignored in Routing module, like:
    
    routes.IgnoreRoute(folderPath)
    
    

How we can validate site in that case?

All recipes in the internet doesn't work. So we need a work around. The solution is pretty simple. All you need is just create another fake site for validating:

  • Create another site yoursite.ssl on the same server in IIS mapped to empty physical folder
  • Create corresponding folders and place the key file inside
  • Place web.config file in key file folder
    
    <?xml version="1.0" encoding="UTF-8"?>
    
    <configuration>
      <system.webServer>
        <validation validateIntegratedModeConfiguration="false" />
      </system.webServer>
      <system.web>
        <authorization>
          <allow users="*" />
        </authorization>
      </system.web>
    </configuration>
    
    
    
  • In IIS manager add new MimeType on site level with values fileExtension="." and mimeType="text/json" (<mimeMap fileExtension="." mimeType="text/json" />)
  • Setup the same binding like in original site, both HTTP and HTTPS
  • Stop original and start fake site. Validate. Get SSL sertificate. Stop fake site and start original.
  • Validate
  • Get SSL sertificate
  • Stop fake site and start original
  • Update certificate

As a conclusion - sometimes all you need is just to think a little and discover a work around :)

Thursday, 22 March 2018

Make site be available & warmed up for the very first user accessing it.

There is an usual issue that opening site can be time-consuming for the first user accessing it after IIS is recycled. But there is an option how to have warmed up site at any time. There are some features starting from IIS 8.

What we need to do:

1) Go to site application pool settings and change Start Mode to "AlwaysRunning"
2) Go to site settings and set Preload Enabled to "True"

The first thing makes application pool running just after IIS is recycled, the second makes warm up first call to the site.

For additional information you can take a look at:

IIS 8 Application pool settings
IIS 8 website settings

Wednesday, 13 December 2017

Best Tool for cloning & synchonization MsSqlServer databases between servers.

If you need to do corresponding things you'd better choose Red Gate SQL Toolbet.

But if you located in Belarus you have to use any site-proxy to be able to download it :) Trial period is 2 weeks.

I tried to find other tools but each of them has its own issues. Red Gate does the stuff in the best manner.

Migration to a new .NET Framework & C# version

For .NET Framework migration we can use following approaches:

  • Changing version one by one for each project in properties window
  • Use any comander with change and replace commands through files with regular expression
  • Install target framework migration tool

For C# version we can use multi-selected projects properties window.

Tuesday, 28 November 2017

Unity and HTTP non-blocking long-term running tasks in Web API

If to continue discussing UNITY we can take a look at the corresponding challenging task ;)

So, we need release UI thread and return to the user message that "long running task started" and at the same time logic must be executing in background.

According to our approach described in the previous article we know that during each controller creation dependency resolver calls BeginScope() and created scope stores all references for instances that needed for resolving any type according to defined UNITY settings for types.

And it's important to write that stuff correctly.

Following code will raise exception "Entity framework DbContext already disposed".


[HttpPost]
[Route("MyAction")]
[AllowAnonymous]
public async Task ReleasingUIThreadOnLongRunningExecution()
{
     await handler.Execute();
     return Ok("My long running execution started");
}

The reason is that after the action executed the scope will be disposed and all instances in it will disposed too.

Here you can see right solution.

  • We get a thread from ThreadPool and assign work to it
  • We create new scope
  • Resolve our handler
  • Execute it
  • Dispose scope


        [HttpPost]
        [Route("MyAction")]
        [AllowAnonymous]
        public async Task ReleasingUIThreadOnLongRunningExecution()
        {
            System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(
             async ct =>
            {
                using (var scope
                      = GlobalConfiguration.Configuration
                              .DependencyResolver.BeginScope())
                {
                    var handler = scope.GetService(typeof(MyLogicHandler)) 
                       as MyLogicHandler;

                    if (handler != null)
                    {
                        await handler.Execute();
                    }
                }
            });

            return Ok("My long running execution started");
        }