Unit testing in Asp .Net 5(vNext) and mvc 6 using XUnit

In this post we will see how to create Unit tests for Asp. Net 5 (vNext) projects.

We will go step by step.

First of all Let us see what is xUnit?

xUnit.net is a free, open source, community-focused unit testing tool for the .NET Framework. Written by the original inventor of NUnit v2, xUnit.net is the latest technology for unit testing C#, F#, VB.NET and other .NET languages.

You can find more about it here.

You might be thinking why we can not do just “Add New Project -> Unit test project” for vNext?
No not yet but yes we can!

Confused?
Well there were not any templates supported to create Unit test in vNext until we had newly added templates in SideWaffle.

Now the question arrises like “What is SideWaffle?”
SideWaffle is an extension

The SideWaffle extension adds a bunch of useful Snippets, Project- and Item Templates to Visual Studio. The purpose is to make your daily work in Visual Studio a richer and more productive experience.

Got it, How to get SideWaffle?
You can directly install it from here.

Now you can directly select template for Unit tests.

How?
File->New Project and navigate to the web node. From there you should see the following list of available templates.

2248.image_thumb_0C9B3FA8

There you go! You have just created an Unit test project which would look as below:

0636.image_thumb_5B77ADEE

Anything in project.json?

{
"version": "1.0.0-*",
"description": "FirstDemoTests Class Library",
"authors": [ "Neel" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",

"dependencies": {
"System.Collections": "4.0.10-beta-23109",
"System.Linq": "4.0.0-beta-23109",
"System.Threading": "4.0.10-beta-23109",
"System.Runtime": "4.0.10-beta-23109",
"Microsoft.CSharp": "4.0.0-beta-23109",

"xunit.runner.dnx": "2.1.0-*",
"xunit": "2.1.0-*",

"YetAnotherWebbyDemo": "1.0.0-*"
},

"commands": {
"test": "xunit.runner.dnx"
},

"frameworks": {
"dnx451": {},
"dnxcore50" : {
      "dependencies": {
        "Microsoft.CSharp": "4.0.0-beta-22816",
        "System.Collections": "4.0.10-beta-22816",
        "System.Linq": "4.0.0-beta-22816",
        "System.Threading": "4.0.10-beta-22816"
      }
    }
 }
}

Now you are all set to write your first method of Unit test in vNext.

Suppose you have method in your AccountController class which validates that User is authorized or not.

So, in your AccountControllerTest class we would write something as below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;

namespace FirstDemoTests
 {
 // This project can output the Class library as a NuGet Package.
 // To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
 public class AccountControllerTests
 {
    [Fact]
    public void IsAuthorizedTest()
    {
       var accountController = new AccountController();
       Assert.True(accountController.IsAuthorized());
    }
 }
 }

You can check your results in Visual Studio. You can build your solution and then open Test Explorer to see the test cases.

That’s it! You can add Unit tests in vNext.

Stay tuned for more updates.

Advertisements

Enable CORS in Asp .Net 5(vNext) and MVC 6

Before going for the basic question “What is CORS?”, Let us take a scenario related to that.

Let us start from very basic example.

Suppose there are 2 URLs which are as below:

http://Alphabet.com/abc.html
http://Alphabet.com/xyz.html

Here above both URLs looks almost same so let us call it “same origin”.

Now, after making little twist we are having some more URLs as below:

http://Alphabet.in //// You are having different domain.
http://www.Alphabet.com/xyz.html //// You have different sub domain
http://Alphabet.com:7000/abc.html //// Oh man you are having different ports

So, as we have seen in above examples URLs does not look similar so let us call it “Different origin”.

Now let us create an Ajax request to some random site like http://Alphabet.com using this jsfiddle :

 $(document).ready(function() { 
    $.ajax({ url: "http://www.Alphabet.com", success: function(data){
        alert(data); 
    } 
   });
 });

And in response you will get:

XMLHttpRequest cannot load http://www.alphabets.com/. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://fiddle.jshell.net’ is therefore not allowed access.

Why??

Because Browser security prevents a web page from making AJAX requests to another domain. This restriction is called the same-origin policy, and prevents a malicious site from reading sensitive data from another site.

Now let us just call(Well not just call but scream) our savior which is CORS!!!!!

56563147

Now the question which we left in starting arrives like, “What is CORS?”

CORS stands for Cross Origin Resource Sharing.

CORS is a W3C standard that allows a server to relax the same-origin policy. Using CORS, a server can explicitly allow some cross-origin requests while rejecting others.

Till now I hope you would have understood what CORS is all about.

Great! Coming to .Net, Does .Net supports CORS?

Yes, It surely does.

To install Microsoft ASP.NET Cross-Origin Support, run the following command in the Package Manager Console:

CORS

How to configure CORS in .Net 5?

First of all we will add CORS service in Startup.cs file as below:

public void ConfigureServices(IServiceCollection services)
{
   services.AddCors();
}

Then You have to configure a CORS policy at application startup in the ConfigureServices method:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors();
    services.ConfigureCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
                                                                        .AllowAnyMethod()
                                                                         .AllowAnyHeader());
}

NOTE: In my example i have taken a configuration policy which allows pretty much everyhing with the name “AllowAll”

Next step would be to apply our settings to our controller actions.

For that there are mainly 2 options:

  • Use this in your attribute on controller actions:
    [EnableCors("AllowAll")]
  • Configure it for every request at application startup:
public void Configure(IApplicationBuilder app)
{
    app.UseCors("AllowAll");
}

Now Suppose we have below 2 projects.

http://www.ConsumeMe.com (has a ASP.NET WebAPI available)
http://www.UseMeToConsume.com

And our ConsumeMe project is having an action method as below:

public class DemoController : Controller
{
    [EnableCors("AllowAll")]
    public string Get()
    {
        return "CORS, You are working!";
    }
}

Let us make an Ajax call from UseMeToConsume to check:

$.ajax({
   url: "http://localhost:1400/api/demo",
   type: "GET",
   success: function (data) {
       alert(data);
   },
   error: function (event) {
       alert("Error!");
   }
});

And thanks to our CORS you will get:

“CORS, You are working!”

There are different options which can be used within CORS.

So i would request to give a look here for more information about different options of CORS in .Net:

Nuget URL for CORS is here

Stay tuned for more updates!

Implement Sessions in Asp .Net 5(vNext) and MVC 6

Imagine you have created an MVC project and you are all set to create a session object because you want to save your current user email.

But after few minutes you will realize that Session object is not working as it was before.

Oh! Why is it so?
It is because .Net team has created a Nuget package for Session which is nothing but a very fresh ASP.NET 5 session state middle ware.

Ok, so How to get it?
To install Microsoft.AspNet.Session, run the following command in the Package Manager Console

sess

Great, so now we can use Session in vNext right?
Well not yet.

We need to update Startup.cs file as below:

public void ConfigureServices(IServiceCollection services)
{ 
    // Adds a default in-memory implementation of IDistributedCache
    services.AddCaching();

    services.AddSession();  
    //// This Method may contain other code as well
}

and in Configure method write below code:

public void Configure(IApplicationBuilder app)
{
    app.UseSession();  
    //// This Method may contain other code as well
}

How to get and set session?
Ok, let us take some examples.

1. Suppose you want to use Session in your controller class:

For that you simply have to write Context.Session to access Session.

Set Session syntax:

public IActionResult Index()
{ 
    ////Context.Session.SetString("First", "I am first!"); ////Before Beta 8
    HttpContext.Session.SetString("First", "I am first!"); ////From Beta 8 onwards
    return View(); 
}

Get Session syntax:

public IActionResult Index()
{ 
    ////var myValue = Context.Session.GetString("First"); ////Before Beta 8
    var myValue = HttpContext.Session.GetString("First"); ////From Beta 8 onwards
    return View(); 
}

2. Suppose you want to use Session in a normal class:

If you’re not in a controller, you can still access the HttpContext by injecting IHttpContextAccessor as shown below:

private readonly IHttpContextAccessor _httpContextAccessor;

public SessionUtility(IHttpContextAccessor httpContextAccessor)
{
    _httpContextAccessor = httpContextAccessor;
}

Set Session syntax:

public void SetSession(string key, string value)
{
    HttpContextAccessor.HttpContext.Session.SetString(key, value);
}

Get Session syntax:

public string GetSession(string key)
{
    return HttpContextAccessor.HttpContext.Session.GetString(key);
 }

So, whole SessionUtility would be as below:

public class SessionUtility 
{
   private readonly IHttpContextAccessor HttpContextAccessor;

   public SessionUtility (IHttpContextAccessor httpContextAccessor)
   {
      HttpContextAccessor = httpContextAccessor;
   }

   public void SetSession(string key, string value)
   {
       HttpContextAccessor.HttpContext.Session.SetString(key, value);
    }

   public string GetSession(string key)
   {
       return HttpContextAccessor.HttpContext.Session.GetString(key);
    }
 }

and it would be registered as below:

services.AddTransient<SessionUtility>();

Here SessionUtility should be registered only as Transient or Scoped and not Singleton as HttpContext is per-request based.

Please note that i have used it with key value pair of string but you can create same Session utility for complex scenario.

Now, Suppose you want to check how many times a Visitor have visited your site.

For that you need to add below code in your startup.cs:

public void Configure(IApplicationBuilder app)
{
    app.UseSession();

    app.Map("/session", subApp =>
    {
        subApp.Run(async context =>
        {
             int visits = 0;
             visits = context.Session.GetInt32("visits") ?? 0;
             context.Session.SetInt32("visits", ++visits);
             await context.Response.WriteAsync("Counting: You have visited our page this many times: " + visits);
        });
     });
}

Remember!
If you have follow above steps and you still can not get the success then you might need a look in your project.json file if it contains below piece of code:

"frameworks": {
 "dnx451": { },
 "dnxcore50": { } // <-- Remove this if it is in your project.json file.
},

Reason?
Because Asp.Net 5 Sessions aren’t supported by the DNX Core Runtime.

Nuget package site: https://www.nuget.org/packages/Microsoft.AspNet.Session/

Session is still in it’s beta versions so there might some changes would come that will be updated in this post.

Stay tuned for more updates!

MVC 6.0.0-beta7 is released

Yes, You heard it right. .Net team has released beta7 of MVC 6 before 2 days and now it is available in Nuget as well you can directly download it.

It contains some new features as well as some bug fixes for previous versions.

What are some features from beta-7?
1. Client side validation of float and double types:

Scenario:
If you have used previous beta for MVC 6 you might know that float and double uses type=”text”.
For example for float it would be as below:

<input type="text" value="1.5" />

Any Impact?:
It disables the browser specific validation of number fields.

Fixed?
Yes, It has been added as a feature for beta 7

2. Returning Ok() from action method:

Scenario:
Suppose you are using MVC5 and there is an Action method in which you are expecting an object.
For that you might do as below:

[HttpGet("{id}")]
public IActionResult Detail(int id)
{
 var ret = xxx.GetById(id);
 if (ret == null) return HttpNotFound($"id {id} does not exist");
 return new HttpStatusCodeResult(ret);
}

Any Impact?:
A missing helper in controller to return an object

Fixed?
Yes, It has been added as a feature for beta 7 and now you can directly return Ok(ret);

3. IMvcBuilder overloads for localization and XML formatters:

Scenario:
If you have used previous beta for MVC 6 you might know that there’s now a configuration experience where you can start with a minimal MVC pipeline and add features to get a customized framework.

public void ConfigureServices(IServiceCollection services)
{
 services
 .AddMvcCore()
 .AddAuthorization()
 .AddJsonFormatters(j => j.Formatting = Formatting.Indented);
}

Here AddMvcCore returns a separate interface IMvcBuilder.

Any Impact?:
Now suppose you want to add EntityFramework then you would write something as below:

public void ConfigureServices(IServiceCollection services)
{
 services
 .AddMvcCore()
 .AddAuthorization()
 .AddJsonFormatters(j => j.Formatting = Formatting.Indented)
 .AddEntityFramework(); // <-- This won't work because we're dealing with `IMvcBuilder` here
}

Fixed?
Both the AddMvc(…) and AddMvcCore(…) extension methods now return a builder API, which can be chained to additional setup methods.
So now above scenario works!

4. Razor attribute behavior to not special case boolean values:

Scenario:

Today if a user writes:

@{
  var isActive = true;
}

<input type="button" onclick="doSomething(@isActive);" />

Any Impact?:
It generates:

<input type="button" onclick="doSomething(onclick);" />.

If isActive is false it removes the content entirely.

Fixed?
In beta 7 Razor boolean and null attribute special case handled correctly.
So in above case If isActive is false it would give:

<input type="button" >

5. Returning ViewComponents from controller actions:

First of all What is view components?

Partial views in MVC has one limitation, which is that they doesn’t have a controller for them. Not having controller makes it hard to have more complex logic associated with the view. View components changes that. Each view component consist of a view and a backing class, it’s not a controller but almost.

Scenario:
In order to render a ViewComponent from a controller, you have to create a view that simply has:

MyViewComponent.cshtml

So if you want to return this ViewComponent you have to return view instead of this Component as below:

public IActionResult MyViewComponent()
{
 return View("MyViewComponent");
}

Fixed?
Yes, in beta 7 they have added ViewComponentResult. So you can directly return ViewComponent.

6. Support for model binding dictionaries

Scenario:

Consider the model:

public class Foo
{
 public Dictionary<int, int> SomeDisctionary{ get; set; }
}

Any Impact?:
The name generated by Html.NameFor(v => v.Values[1]) is Values[1] however this expression does not get model bound.

Fixed?
Yes, in beta 7 they have added support for model binding dictionaries.

7. Added URL resolving TagHelper to replace Razor ~/ functionality

Scenario:

Classic Razor would resolve the value of any HTML attribute that started with ~/ as an application relative URL. This led to some invalid scenarios where users would provide attribute values such as ~/folder/file.txt and get inaccurate URL resolutions. In addition, this feature couldn’t be easily disabled.

Fixed:

Yes, .Net team decided to create the UrlResolutionTagHelper to take over ~/ resolution.
But for that you need to disable Url resolution as shown below:

@removeTagHelper "Microsoft.AspNet.Mvc.Razor.TagHelpers.UrlResolutionTagHelper, Microsoft.AspNet.Mvc.Razor"

Additionally there are some bugs fixed in this beta version.

You can have 6.0.0-beta7 here at Nuget:

Stay tuned for more updates.

Blog at WordPress.com.

Up ↑