European ASP.NET MVC 4 and MVC 5 Hosting

BLOG about ASP.NET MVC 3, ASP.NET MVC 4, and ASP.NET MVC 5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET Core Hosting - HostForLIFE.eu :: How to Use Sessions and HttpContext in ASP.NET 5 and MVC6

clock February 24, 2017 06:56 by author Scott

If you’ve started work on a new ASP.NET 5, MVC 6 application you may have noticed that Sessions don’t quite work the way they did before. Here’s how to get up and running the new way.

Remove DNX Core Reference

Many simple ASP.NET components aren’t supported by the DNX Core Runtime. These usually surface with weird build errors. It’s much easier to just remove it from your project.json file. If it’s already not there, beautiful you don’t need to do anything

"frameworks": {
    "dnx451": { },
    "dnxcore50": { } // <-- Remove this line
},

Add Session NuGet Package

Add the Microsoft.AspNet.Session NuGet package to your project.

VERSION WARNING: If you’re using ASP.NET 5 before RTM, make sure the beta version is the same across your whole project. Just look at your references and make sure they all end with beta8 (or whichever version you’re using).

Update startup.cs

Now that we have the Session nuget package installed, we can add sessions to the OWIN pipline.

Open up startup.cs and add the AddSession() and AddCaching() lines to the ConfigureServices(IServiceCollection services)

// Add MVC services to the services container.
services.AddMvc();
services.AddCaching(); // Adds a default in-memory implementation of IDistributedCache
services.AddSession();

Next, we’ll tell OWIN to use a Memory Cache to store the session data. Add the UseSession() call below.

// IMPORTANT: This session call MUST go before UseMvc()
app.UseSession();

// Add MVC to the request pipeline.
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action}/{id?}",
        defaults: new { controller = "Home", action = "Index" });

    // Uncomment the following line to add a route for porting Web API 2 controllers.
    // routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
});

Where’s the Session variable gone?

Relax it’s still there, just not where you think it is. You can now find the session object by using HttpContext.Session. HttpContext is just the current HttpContext exposed to you by the Controller class.

If you’re not in a controller, you can still access the HttpContext by injecting IHttpContextAccessor.

Let’s go ahead and add sessions to our Home Controller:

public class HomeController : Controller
{
    public IActionResult Index()
    {
        HttpContext.Session.SetString("Test", "Ben Rules!");
        return View();
    }

    public IActionResult About()
    {
        ViewBag.Message = HttpContext.Session.GetString("Test");

        return View();
    }
}

You’ll see the Index() and About() methods making use of the Session object. It’s pretty easy here, just use one of the Set() methods to store your data and one of the Get() methods to retrieve it.

Just for fun, let’s inject the context into a random class:

public class SomeOtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private ISession _session => _httpContextAccessor.HttpContext.Session;

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

    public void TestSet()
    {
        _session.SetString("Test", "Ben Rules!");
    }

    public void TestGet()
    {
        var message = _session.GetString("Test");
    }
}

Let’s break this down.

Firstly I’m setting up a private variable to hold the HttpContextAccessor. This is the way you get the HttpContext now.

Next I’m adding a convenience variable as a shortcut directly to the session. Notice the =>? That means we’re using an expression body, aka a shortcut to writing a one liner method that returns something.

Moving to the contructor you can see that I’m injecting the IHttpContextAccessor and assigning it to my private variable. If you’re not sure about this whole dependency injection thing, don’t worry, it’s not hard to get the hang of (especially constructor injection like I’m using here) and it will improve your code by forcing you to write it in a modular way.

But wait a minute, how do I store a complex object?

How do I store a complex object?

I’ve got you covered here too. Here’s a quick JSON storage extension to let you store complex objects nice and simple.

public static class SessionExtensions
{
    public static void SetObjectAsJson(this ISession session, string key, object value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }

    public static T GetObjectFromJson<T>(this ISession session, string key)
    {
        var value = session.GetString(key);

        return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
    }
}

Now you can store your complex objects like so:

var myComplexObject = new MyClass();
HttpContext.Session.SetObjectAsJson("Test", myComplexObject);

and retrieve them just as easily:

var myComplexObject = HttpContext.Session.GetObjectFromJson<MyClass>("Test");

Use a Redis or SQL Server Cache instead

Instead of using services.AddCaching() which implements the default in-memory cache, you can use either of the following.

Firstly, install either one of these nuget packages:

  • Microsoft.Framework.Caching.SqlServer
  • Microsoft.Framework.Caching.Redis

Secondly, add the appropriate code snippet below:

// Microsoft SQL Server implementation of IDistributedCache.
// Note that this would require setting up the session state database.
services.AddSqlServerCache(o =>
{
                o.ConnectionString = "Server=.;Database=ASPNET5SessionState;Trusted_Connection=True;";
                o.SchemaName = "dbo";
                o.TableName = "Sessions";
});

 

// Redis implementation of IDistributedCache.
// This will override any previously registered IDistributedCache service.
services.AddSingleton<IDistributedCache, RedisCache>();

 



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Angular 2 Contact Form Component for ASP.NET MVC 6

clock February 16, 2017 07:20 by author Scott

In this post, I will show you simple tutorial about how to create a simple contact form using Angular 2 and ASP.NET MVC 6. Ok, let’s get started.

The Component

Contact.cshtml

We’ll start off with a simple contact form. I’m asking the user for his name, e-mail address, a subject and of course the message itself. 
You’ll notice that I’m also using a bit of Bootstrap css classes. You however can of course use anything you want to style the contact form.

<div>
    <form #f="ngForm" (ngSubmit)="onSubmit(contact)">
        <div>
            <div class="form-group required">
                <label for="name">Name</label>
                <input type="text" [(ngModel)]="contact.Name" name="contact.Name" required="Please enter your name" class="form-control text-input" id="name" placeholder="Name"/>
            </div>
            <div class="form-group required">
                <label for="email">E-mail</label>
                <input type="email" [(ngModel)]="contact.Email" name="contact.Email" required="Please enter your e-mail address" class="form-control text-input" id="email" placeholder="E-mail"/>
            </div>
        </div>
        <div>
            <div class="form-group required">
                <label for="subject">Subject</label>
                <input type="text" [(ngModel)]="contact.Subject" name="contact.Subject" required="A subject is needed" class="form-control text-input" id="subject" placeholder="Subject"/>
            </div>
        </div>
        <div>
            <div class="form-group required">
                <label for="message">Message</label>
                <textarea type="text" [(ngModel)]="contact.Message" name="contact.Message" required="A message is needed" class="form-control" id="message" placeholder="Message..."></textarea>
            </div>
        </div>
        <div>
            <div>
                <button type="submit" class="btn btn-success">Send</button>
            </div>
        </div>
    </form>
</div>

Contact.ts

This the most important part of this post. I’ve written the code in Typescript. 
Due to an issue I couldn’t seem to resolve between MVC6 and Angular 2 I was forced to the URLSearchParams from Angular to send my data to the server. I hope to update this one day so I only have to send the complete object to the server.

import {Component} from '@angular/core';
import {Http, Headers, URLSearchParams} from '@angular/http';

@Component({
    selector: 'contact',
    templateUrl: '/angular/contact'
})

export class ContactFormComponent {
    http = undefined;
    contact = { Name: undefined, Subject: undefined, Email: undefined, Message: undefined };
    loading = true;

    constructor(http: Http) {
        this.http = http;
        this.loading = false;
    }

    onSubmit() {
        this.loading = true;
        let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
        var params = new URLSearchParams();
        params.set('Name', this.contact.Name);
        params.set('Subject', this.contact.Subject);
        params.set('Message', this.contact.Message);
        params.set('Email', this.contact.Email);
        this.http.post('/contact/send', params.toString(), { headers: headers }).subscribe(this.messageSend());
    }

    messageSend() {
        this.contact = { Name: undefined, Subject: undefined, Email: undefined, Message: undefined };
        this.loading = false;
    }
}

This was the biggest part, now what’s left is the connection on the server itself.

Start.cs

First we’ll setup the routes. This is very easy. I’ve set up a rout to go to the contact form itself and one for sending the information to the server.

public class Startup
{
                public void ConfigureServices(IServiceCollection services)
                {
                                //I'm using MVC... So I'm adding MVC.
                                services.AddMvc();
                }

                public void Configure(IApplicationBuilder app)
                {
                                //I have some static files, like images and css in my wwwroot folder. So I need to add these.
                                app.UseStaticFiles();
                                app.UseMvc(m =>
                                {
                                                //Route to open the page with the form.
                                                m.MapRoute("contact", "contact", new { controller = "Contact", action = "Contact" });
                                                //Route to post the data
                                                m.MapRoute("contact-send", "contact/send", new { controller = "Contact", action = "SendContact" });
                                });
                }

                // Entry point for the application.
                public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}

ContactVm.cs

This is going to be the ViewModel. I use this to map the JSON request to a nice and easy model we can use on our controller.

public class ContactVm
{
                [Required]
                [DataType(DataType.Text)]
                public string Name { get; set; }
                [Required]
                [DataType(DataType.EmailAddress)]
                public string Email { get; set; }
                [Required]
                [DataType(DataType.Text)]
                public string Subject { get; set; }
                [Required]
                [DataType(DataType.MultilineText)]
                public string Message { get; set; }
}

ContactController.cs

The last part is our controller itself where the data is being received on the server. Nothing special here, I’m just using the above viewmodel as a parameter.

public class ContactController : Controller
{
                public ContactController() { }

                public IActionResult Contact()
                {
                                return View();
                }             

                [HttpPost]
                public void SendContact(ContactVm contact)
                {
                                //Do something with the contact form...
                }
}

By using the above code you’ll be able create a contact form in Angular 2 and make it interact with and MVC 6 server-side.
Keep in mind the both frameworks are still in development and can contain errors.



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Use AngularJS with MVC 6 Web API

clock February 10, 2017 08:46 by author Scott

This post will walk you through the step-by-step procedure on building a simple ASP.NET 5 application using AngularJS with Web API.

Before we dig further let’s talk about a quick overview of AngularJS and Web API in MVC 6.

Introducing AngularJS

AngularJS is a client-side MVC framework written in JavaScript. It runs in a web browser and greatly helps us (developers) to write modern, single-page, AJAX-style web applications. It is a general purpose framework, but it shines when used to write CRUD (Create Read Update Delete) type web applications.

Introducing Web API

ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework. In ASP.NET 5, Web API is now part of MVC 6. Read more here

Creating an ASP.NET 5 Project

To start, fire up Visual Studio 2015 and create a new ASP.NET 5 project by selecting File > New Project. In the dialog, under Templates > Visual C#, select ASP.NET Web Application as shown in the figure below: 

Name your project to whatever you like and then click OK. For this example I named the project as “AngularJS101”. Now after that you should be able to see the “New ASP.NET Project” dialog:

Now select ASP.NET 5 Preview Empty template from the dialog above. Then click OK to let Visual Studio generate the necessary files and templates needed for you. You should be able to see something like below:

Adding the Scripts folder

The next thing to do is to create a new folder called “Scripts”. This folder will contain all the JavaScript files needed in our application:

Getting the Required Packages

ASP.NET 5 now supports three main package managers: NuGet, NPM and Bower.

Package Manager

A package manager enables you to easily gather all resources that you need for building an application. In other words you can make use of package manager to automatically download all the resources and their dependencies instead of manually downloading project dependencies such as jQuery, Bootstrap and AngularJS in the web.

NuGet

NuGet manages .NET packages such as Entity Framework, ASP.NET MVC and so on. You typically specify the NuGet packages that your application requires within project.json file.

NPM

NPM is one of the newly supported package manager in ASP.NET 5. This package manager was originally created for managing packages for the open-source NodeJS framework. The package.json is the file that manages your project’s NPM packages.

Bower

Bower is another supported package manager in ASP.NET 5. It was created by Twitter that is designed to support front-end development. You can use Bower to manage client-side resources such as jQuery, AngularJS and Bootstrap.

For this example we need to use NPM to install the resources we need in our application such as Grunt and the Grunt plugins. To do this just right click in your Project (in this case AngularJS101) and select Add > New Item. In the dialog select NPM configuration file as shown in the figure below:

Click Add to generate the file for you. Now open package.json file and modify it by adding the following dependencies:

{
    "version": "1.0.0",
    "name": "AngularJS101",
    "private": true,
    "devDependencies": {
        "grunt": "0.4.5",
        "grunt-contrib-uglify": "0.9.1",
        "grunt-contrib-watch": "0.6.1"
    }
}

Notice that you get Intellisense support while you edit the file. A matching list of NPM package names and versions shows as you type.

In package.json file, from the code above, we have added three (3) dependencies named grunt, grunt-contrib-uglify and grunt-contrib-watch NPM packages that are required in our application.

Now save the package.json file and you should be able to see a new folder under Dependencies named NPM as shown in the following:

Right click on the NPM folder and select Restore Packages to download all the packages required. Note that this may take a bit to finish the download so just be patient and wait ;). After that the grunt, grunt-contrib-uglify and grunt-contrib-watch NPM packages should now be installed as shown in the following:

Configuring Grunt

Grunt is an open-source tool that enables you to build client-side resources for your project. For example, you can use Grunt to compile your LESS or Saas files into CSS. Adding to that, Grunt can also be used to minify CSS and JavaScript files.

In this example, we will use Grunt to combine and minify JavaScript files. We will configure Grunt so that it will take all the JavaScript files from the Scripts folder that we created earlier, combine and minify the files, and finally save the results to a file named app.js within the wwwroot folder.

Now right click on your project and select Add > New Item. Select Grunt Configuration file from the dialog as shown in the figure below:

Then click Add to generate the file and then modify the code within the Gruntfile.js file so it will look like this:

module.exports = function (grunt) { 
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.initConfig({
        uglify: {
            my_target: {
                files: { 'wwwroot/app.js': ['Scripts/app.js', 'Scripts/**/*.js'] }
            }
        },

        watch: {
            scripts: {
                files: ['Scripts/**/*.js'],
                tasks: ['uglify']
            }
        }
    });

    grunt.registerTask('default', ['uglify', 'watch']);
};

The code above contains three sections. The first one is used to load each of the Grunt plugins that we need from the NPM packages that we configured earlier. The initConfig() is responsible for configuring the plugins. The Uglify plugin is configured so that it combines and minifies all the files from the Scripts folder and generate the result in a file named app.js within wwwroot folder. The last section contains the definitions for your tasks. In this case we define a single ‘default’ task that runs ‘uglify’ and then watches for changes in our JavaScript file.

Now save the file and let’s run the Grunt file using Visual Studio Task Runner Explorer. To do this, go to View > Other Windows > Task Runner Explorer in Visual Studio main menu. In the Task Runner Explorer make sure to hit the refresh button to load the tasks for our application. You should see something like this:

Now right click on the default task and select Run. You should be able to see the following output:

Configuring ASP.NET MVC

There are two main files that we need to modify to enable MVC in our ASP.NET 5 application.

First, we need to modify the project.json file to in include MVC 6 under dependencies:

    "webroot": "wwwroot",
    "version": "1.0.0-*",
    "dependencies": {
        "Microsoft.AspNet.Server.IIS": "1.0.0-beta3",
        "Microsoft.AspNet.Mvc": "6.0.0-beta3"
    },
    "frameworks": {
        "aspnet50": { },
        "aspnetcore50": { }
    },

Make sure to save the file to restore the packages required. The project.json file is used by the NuGet package manager to determine the packages required in your application. In this case we’ve added Microsoft.AspNet.Mvc.

Now the last thing is to modify the Startup.cs file to add the MVC framework in the application pipeline. Your Startup.cs file should now look like this:

using System; 
using Microsoft.AspNet.Builder; 
using Microsoft.AspNet.Http; 
using Microsoft.Framework.DependencyInjection;

namespace AngularJS101 
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services){
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app){
            app.UseMvc();
        }
    }
}

The ConfigureServices() method is used to register MVC with the ASP.NET 5 built-in Dependency Injection Framework (DI). The Configure() method is used to register MVC with OWIN.

Adding Models

The next step is to create a model that we can use to pass data from the server to the browser/client. Now create a folder named “Models” under the root of your project. Within the “Models” folder, create a class named “DOTAHero” and add the following code below:

using System;

namespace AngularJS101.Models 
{
    public class DOTAHero
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
    }
}

Create another class called “HeroManager” and add the following code below:

using System.Collections.Generic; 
using System.Linq;

namespace AngularJS101.Models 
{
    public class HeroManager
    {
        readonly List<DOTAHero> _heroes = new List<DOTAHero>() {
            new DOTAHero { ID = 1, Name = "Bristleback", Type="Strength"},
            new DOTAHero { ID = 2, Name ="Abbadon", Type="Strength"},
            new DOTAHero { ID = 3, Name ="Spectre", Type="Agility"},
            new DOTAHero { ID = 4, Name ="Juggernaut", Type="Agility"},
            new DOTAHero { ID = 5, Name ="Lion", Type="Intelligence"},
            new DOTAHero { ID = 6, Name ="Zues", Type="Intelligence"},
            new DOTAHero { ID = 7, Name ="Trent", Type="Strength"},
        };
        public IEnumerable<DOTAHero> GetAll { get { return _heroes; } }

        public List<DOTAHero> GetHeroesByType(string type) {
            return _heroes.Where(o => o.Type.ToLower().Equals(type.ToLower())).ToList();
        }

 public DOTAHero GetHeroByID(int Id) {
            return _heroes.Find(o => o.ID == Id);
        }
    }
}

The HeroManager class contains a readonly property that contains a list of heroes. For simplicity, the data is obviously static. In real scenario you may need to get the data in a storage medium such as database or any files that stores your data. It also contains a GetAll property that returns all the heroes and a GetHeroesByType() method that returns a list of heroes based on the hero type, and finally a GetHeroByID() method that returns a hero based on their ID.

Adding Web API Controller

For this particular example, we will be using Web API for passing data to the browser/client.

Unlike previous versions of ASP.NET, MVC and Web API controllers used the same controller base class. Since Web API is now part of MVC 6 then we can start creating Web API controllers because we already pulled the required NuGet packages for MVC 6 and configured MVC 6 in startup.cs.

Now add an “API” folder under the root of the project:

Then add a Web API controller by right-clicking the API folder and selecting Add > New Item. Select Web API Controller Class and name the controller as “HeroesController” as shown in the figure below:

Click Add to generate the file for you. Now modify your HeroesController class so it will look like this:

using System.Collections.Generic; 
using Microsoft.AspNet.Mvc; 
using AngularJS101.Models;

namespace AngularJS101.API.Controllers 
{
    [Route("api/[controller]")]
    public class HeroesController : Controller
    {
        // GET: api/values
        [HttpGet]
        public IEnumerable<DOTAHero> Get()
        {
            HeroManager HM = new HeroManager();
            return HM.GetAll;
        }

        // GET api/values/7
        [HttpGet("{id}")]
        public DOTAHero Get(int id)
        {
            HeroManager HM = new HeroManager();
            return HM.GetHeroByID(id);
        }

    }
}

At this point we will only be focusing on GET methods to retrieve data. The first GET method returns all the heroes available by calling the GetAll property found in HeroManager class. The second GET method returns a specific hero data based on the ID.

You can test whether the actions are working by running your application in the browser and appending the /api/heroes in the URL. Here are the outputs for both GET actions:

Route: /api/heroes

Route: /api/heroes/7

Creating an AngularJS Application

Visual Studio 2015 includes templates for creating AngularJS modules, controllers, directives and factories. For this example we will be displaying the list of heroes using an AngularJS template.

Adding an AngularJS Module

To get started lets create an AngularJS module by right-clicking on the Scripts folder and selecting Add > New Item. Select AngularJS Module as shown in the figure below.

Click Add to generate the file and copy the following code for our AngularJS module:

(function () {
    'use strict';

    angular.module('heroesApp', [
        'heroesService'      
    ]);
})();

The code above defines a new AngularJS module named “heroesApp”. The heroesApp has a dependency on another AngularJS module named “heroesService” which we will create later in the next step.

Adding an AngularJS Controller

The next thing to do is to create a client-side AngularJS Controller. Create a new folder called “Controllers” under the Script folder as in the following:

 

Click Add and copy the following code below within your heroesController.js file:

(function () {
    'use strict';

    angular
        .module('heroesApp')
        .controller('heroesController', heroesController);

    heroesController.$inject = ['$scope','Heroes'];

    function heroesController($scope, Heroes) {
        $scope.Heroes = Heroes.query();
    }
})();

The code above depends on the Heroes service that supplies the list of heroes. The Heroes service is passed to the controller using dependency injection (DI). The $inject() method call enables DI to work. The Heroes service is passed as the second parameter to the heroesController() function.

Adding the Heroes Service

We will use an AngularJS Heroes service to interact with our data via Web API. Now add a new folder called “Services” within the Script folder. Right click on the Services folder and select Add > New Item. From the dialog select AngularJS Factory and name it as “heroesService.js” as in the following:

Now click Add and then replace the generated default code with the following:

(function () {
    'use strict';

    var heroesService = angular.module('heroesService', ['ngResource']);
    heroesService.factory('Heroes', ['$resource',
        function ($resource) {
            return $resource('/api/heroes', {}, {
                query: { method: 'GET', params: {}, isArray: true}
            });
        }
    ]);
})();

The code above basically returns a list of heroes from the Web API action. The $resource object performs an AJAX request using a RESTful pattern. The heroesService is associated with the /api/heroes route on the server. This means that when you perform a query against the service from your client-side code, the Web API HeroesController is invoked to return a list of heroes.

Adding an AngularJS Template

Let’s add an AngularJS template for displaying the list of heroes. To do this we will need an HTML page to render in the browser. In the wwwroot folder add a new HTML page and name it as “index” for simplicity. Your application structure should now look like this:

The wwwroot folder is a special folder in your application. The purpose is that the wwwroor folder should contain all contents of your website such as HTML files and images needed for your website.

You should not place any of your source code within the wwwroot folder. Instead source codes such as MVC controllers’ source, model classes and unminified JavaScript and LESS files should be placed outside of the wwwroot folder.

Now replace the content of index.html with the following:

<!DOCTYPE html>  
<html ng-app="heroesApp"> 
<head> 
    <meta charset="utf-8" />
    <title>DOTA 2 Heroes</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-resource.js"></script>
    <script src="app.js"></script>
</head> 
<body ng-cloak> 
    <div ng-controller="heroesController">
        <h1>DOTA Heroes</h1>
        <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Type</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="hero in Heroes">
                    <td>{{hero.ID}}</td>
                    <td>{{hero.Name}}</td>
                    <td>{{hero.Type}}</td>
                </tr>
            </tbody>
        </table>
    </div>
</body> 
</html> 

There are several things to point out from the markup above: 
The html element is embedded with the ng-app directive. This directive associates the heroesApp with the HTML file.

In the script section, you will notice that I use Google CDN for referencing AngularJS and related libraries. Besides being lazy, it’s my intent to use CDN for referencing standard libraries such as jQuery, AngularJS and Bootstrap to boost application performance. If you don’t want to use CDN then you can always install AngularJS packages using Bower.

The body element is embedded with the ng-cloak directive. This directive hides an AngularJS template until the data has been loaded in the page. 
The div element within the body block is embedded with the ng-controller directive. This directive associates the heroesController and renders the data within the div element.

Finally, the ng-repeat directive is added to the tr element of the table. This will create row for each data that retrieved from the server.

Output

Here’s the output below when running the page and navigating to index.html:

That’s it! It is more fun to play DOTA!

 



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: New Configuration and AppSetings for ASP.NET MVC 6

clock January 17, 2017 10:35 by author Scott

There’s a new place to put the app settings for your MVC6 ASP.NET Core application. Web.config is gone but the new solution is great, you get a dependency injected POCO with strongly typed settings instead!

New Settings File - appsettings.json

Instead of web.config, all your settings are now located in appsettings.json. Here’s what the default one looks like, though I’ve also added an AppSettings section:

{
  "AppSettings": {
    "BaseUrls": {
      "API": "https://localhost:44307/",
      "Auth": "https://localhost:44329/",
      "Web": https://localhost:44339/
    },
    "AnalyticsEnabled": true
  },
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-AppSettings1-ad2c59cc-294a-4e72-bc31-078c88eb3a99;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Verbose",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Notice that we’re using JSON instead of XML now. This is pretty great with one big exception, No Intellisense.

Create an AppSettings class

If you’re used to using ConfigurationManager.AppSettings["MySetting"] in your controllers then you’re out of luck, instead you need to setup a class to hold your settings. As you can see above I like to add an “AppSettings” section to the config that maps directly to an AppSettings POCO. You can even nest complex classes as deep as you like:

public class AppSettings
{
    public BaseUrls BaseUrls { get; set; }
    public bool AnalyticsEnabled { get; set; }
}

public class BaseUrls
{
    public string Api { get; set; }
    public string Auth { get; set; }
    public string Web { get; set; }
}  

Configure Startup.cs

Now that we have a class to hold our settings, lets map the data from our appsettings.json. You can do it in a couple of ways

Automatically bind all app settings:

public IServiceProvider ConfigureServices(IServiceCollection services)
{           
    services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
}

or if you need to alter or transform anything you can assign each property manually:

public IServiceProvider ConfigureServices(IServiceCollection services)
{           
    services.Configure<AppSettings>(appSettings =>
    {
        appSettings.BaseUrls = new BaseUrls()
        {
            // Untyped Syntax - Configuration[""]
            Api = Configuration["AppSettings:BaseUrls:Api"],
            Auth = Configuration["AppSettings:BaseUrls:Auth"],
            Web = Configuration["AppSettings:BaseUrls:Web"],
        };               

        // Typed syntax - Configuration.Get<type>("")
        appSettings.AnalyticsEnabled = Configuration.Get<bool>("AppSettings:AnalyticsEnabled");
    });
}

Using the settings

Finally we can access our settings from within our controllers. We’ll be using dependency injection, so if you’re unfamiliar with that, get ready to learn!

public class HomeController : Controller
{
    private readonly AppSettings _appSettings;

    public HomeController(IOptions<AppSettings> appSettings)
    {
        _appSettings = appSettings.Value;
    }

    public IActionResult Index()
    {
        var webUrl = _appSettings.BaseUrls.Web;

        return View();
    }
}

There are a few important things to note here:

The class we are injecting is of type IOptions<AppSettings>. If you try to inject AppSettings directly it won’t work.

Instead of using the IOptions class throughout the code, instead I set the private variable to just AppSettings and assign it in the constructor using the .Value property of the IOptions class.

By the way, the IOptions class is essentially a singleton. The instance we create during startup is the same throughout the lifetime of the application.

While this is a lot more setup than the old way of doing things, I think it forces developers to code in a cleaner and more modular way.



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Binding and Minification in SiteCore MVC

clock January 6, 2017 07:01 by author Scott

This is a quick blog post on how to implement bundling and minification in Sitecore MVC project.  During development phase, it is always good to have multiple Javascripts and CSS files for better readability and maintainability of code.  But multiple Javascripts and CSS files degrade the performance of production website and also increase the load time of webpages as it requires multiple HTTP requests from browser to server.  Bundling and minification reduce the size of Javascript and CSS files and bundle multiple files into a single file and make the site perform faster by making fewer HTTP requests. Below steps explain how to implement bundling and minification for Sitecore MVC project: 

1. Add Microsoft ASP.NET Web Optimization Framework to your solution from nuget or run the following command in the Package Manager Console to install Microsoft ASP.NET Web Optimization Framework.

PM> Install-Package Microsoft.AspNet.Web.Optimization

2. Create your CSS and Javascript bundles in “BundleConfig” class under App_Start folder and add reference of "System.Web.Optimization" namespace.

public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            //js bundling using wildcard character *
            bundles.Add(new ScriptBundle("~/bundles/js").Include("~/assets/js/*.js"));

            //css bundling using wildcard character *
            bundles.Add(new StyleBundle("~/bundles/css").Include("~/assets/css/*.css"));
        }
    }

3. Register bundle in the Application_Start method in the Global.asax file. If you are using Multi-site instance of Sitecore MVC then recommend way to implement bundling logic is by creating a new processor into the initialize pipeline. 

protected void Application_Start(object sender, EventArgs e)
        {
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

We can override the value of the debug attribute in code by using EnableOptimizations property of the BundleTable class.

protected void Application_BeginRequest(object sender, EventArgs e)
        {
            EnableBundleOptimizations();
        }

        private void EnableBundleOptimizations()
        {
            string debugMode = Request.QueryString["debug"];
            if (!string.IsNullOrEmpty(debugMode) && string.Equals(debugMode, "true", StringComparison.InvariantCultureIgnoreCase))
            {
                BundleTable.EnableOptimizations = false;
            }
            else
            {
                BundleTable.EnableOptimizations = true;
            }
        }

Here in Application_BeginRequest method of Global.asax I am calling one custom method EnableBundleOptimizations() which sets the value of EnableOptimizations property to true or false based on value of querystring “debug”. Main idea behind this logic is that we can check/debug CSS or Javascript file on production by passing querystring parameter debug as true. 

5. Replace Javascripts and CSS references in layout or rendering view with below code:

@Styles.Render("~/bundles/css")
@Styles.Render("~/bundles/js")

6. In web.config set an ignore url prefix for your bundle so that Sitecore won’t try to resolve the URL to the bundle. Update setting IgnoreUrlPrefixes according to your bundle name:

<setting name="IgnoreUrlPrefixes" value="/sitecore/default.aspx|/trace.axd|/webresource.axd|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.DialogHandler.aspx|/sitecore/shell/applications/content manager/telerik.web.ui.dialoghandler.aspx|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.SpellCheckHandler.axd|/Telerik.Web.UI.WebResource.axd|/sitecore/admin/upgrade/|/layouts/testing|/bundles/js|/bundles/css"/>

7. Now compile your solution and verify that bundling and minification is enabled by checking view source of webpage.

Pass querystring as debug=true in url and now verify view source of webpage. Bundling and minification is not enabled. This enables us to debug Javascript and CSS files in production website. 



European ASP.NET MVC Hosting - HostForLIFE.eu :: Custom Model Binders in ASP.NET MVC

clock December 22, 2016 06:31 by author Scott

In ASP.NET MVC, our system is built such that the interactions with the user are handled through Actions on our Controllers. We select our actions based on the route the user is using, which is a fancy way of saying that we base it on a pattern found in the URL they’re using. If we were on a page editing an object and we clicked the save button we would be sending the data to a URL somewhat like this one.

Notice that in our route that we have specified the name of the object that we’re trying to save. There is a default Model Binder for this in MVC that will take the form data that we’re sending and bind it to a CLR objects for us to use in our action. The standard Edit action on a controller looks like this.

[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    try
    {
        // TODO: Add update logic here
 
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

If we were to flesh some of this out the way it’s set up here, we would have code that looked a bit like this.

[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    try
    {
        Profile profile = _profileRepository.GetProfileById(id);

        profile.FavoriteColor = collection["favorite_color"];
        profile.FavoriteBoardGame = collection["FavoriteBoardGame"];

        _profileRepository.Add(profile);

        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

What is bad about this is that we are accessing the FormCollection object which is messy and brittle. Once we start testing this code it means that we are going to be repeating code similar to this elsewhere. In our tests we will need to create objects using these magic strings. What this means is that we are now making our code brittle. If we change the string that is required for this we will have to go through our code correcting them. We will also have to find them in our tests or our tests will fail. This is bad. What we should do instead is have these only appear on one place, our model binder. Then all the code we test is using CLR objects that get compile-time checking. To create our Custom Model Binder this is all we need to do is write some code like this.

public class ProfileModelBinder : IModelBinder
{
    ProfileRepository _profileRepository = new ProfileRepository();

    public object BindModel(ControllerContext controllerContext,
        ModelBindingContext bindingContext)
    {
        int id = (int)controllerContext.RouteData.Values["Id"];
        Profile profile = _profileRepository.GetProfileById(id);

        profile.FavoriteColor = bindingContext
            .ValueProvider
            .GetValue("favorite_color")
            .ToString();


        profile.FavoriteBoardGame = bindingContext
            .ValueProvider
            .GetValue("FavoriteBoardGame")
            .ToString();

        return profile;
    }
}

Notice that we are using the form collection here, but it is limited to this one location. When we test we will just have to pass in the Profile object to our action, which means that we don’t have to worry about these magic strings as much, and we’re also not getting into the situation where our code becomes so brittle that our tests inhibit change. The last thing we need to do is tell MVC that when it is supposed to create a Profile object that it is supposed to use this model binder. To do this, we just need to Add our binder to the collection of binders in the Application_Start method of our GLobal.ascx.cs file. It’s done like this. We say that this binder is for objects of type Profile and give it a binder to use.

ModelBinders.Binders.Add(typeof (Profile), new ProfileModelBinder());

Now we have a model binder that should let us keep the messy code out of our controllers. Now our controller action looks like this.

[HttpPost]
public ActionResult Edit(Profile profile)
{
    try
    {
        _profileRepository.Add(profile);

        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

That looks a lot cleaner to me, and if there were other things I needed to do during that action, I could do them without all of the ugly binding logic.

 



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: How to Implement Sessions in ASP.NET MVC 6

clock December 15, 2016 07:36 by author Scott

Imagine you have created an MVC project and you are all set to create a session object in order to save your current user Email but after few minutes, you realize that the 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 middleware.

OK. So, how to get it?

To install Microsoft.AspNet.Session, run the command, given below, in the Package Manager Console. 

We need to update the startup.cs file, as shown 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?

Let's take some examples.

1. Suppose, you want to use Session in your controller class. For it, 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:

services.AddTransient<SessionUtility>();  

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

Please note, I have used it with the key value pair of the string, but you can create the same SessionUtility for the complex scenarios.

Now, suppose you want to check how many times a visitor has visited your site.

For it, you need to add the code, given below, 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);  
        });  
    });  
}  

Important!

If you have followed the steps, given above and you still can't get success, you might need a look in your project.json file for the following piece of the code. Well, it should be there.

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

Why?

ASP.NET5 Sessions aren’t supported by the DNX Core Runtime.

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

Session is still in its beta versions. Thus, some changes might come, which I will update in this post.

Stay tuned for more updates!

 



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: ASP.NET MVC 6 Dependency Injection

clock October 5, 2016 23:32 by author Scott

Dependency injection (DI) has been possible in previous versions of MVC. With each new version DI has been easier to implement and, with MVC6, DI is supplied right out of the box. In this article we’ll look at how the new DI implementation works, what are its weaknesses and how we can replace it with our favorite DI framework.

What’s new

The unification of APIs across ASP.NET is a common theme throughout ASP.NET 5, and dependency injection is no different. The new ASP.NET stack including: MVC, SignalR and Web API, etc. rely on a built-in minimalistic DI container. The core features of the DI container have been abstracted out to the IServiceProvider interface and are available throughout the stack. Because the IServiceProvider is the same across all components of the ASP.NET framework a single dependency can be resolved from any part of the application.

The DI container supports just 4 modes of operation:

  • Instance – a specific instance is given all the time. You are responsible for its initial creation.
  • Transient – a new instance is created every time.
  • Singleton – a single instance is created and it acts like a singleton.
  • Scoped – a single instance is created inside the current scope. It is equivalent to Singleton in the current scope.

BASIC SETUP

Let’s walk through setting up DI in a MVC application. To demonstrate the basics, we’ll resolve the dependency for the service used to get project data. We don’t need to know anything about the service other than that it implements the IProjectService interface, an interface custom to our demo project. IProjectService has one method,GetOrganization(), that method retrieves an organization and its corresponding list of projects.

public interface IProjectService
{
    string Name { get; }
    Organization GetOrganization();
}

public class Organization
{
    public string Name { get; set; }
    [JsonProperty("Avatar_Url")]
    public string AvatarUrl { get; set; }
    public IQueryable<Project> Projects { get; set; }
}

We’ll use the IProjectService to get the organization data and display it in a view. Let’s start by setting up the controller where the service will be used. We’ll use constructor injection by creating a new constructor method for our controller that accepts anIProjectService. Next, the Index action will callGetOrganization, sending the data to the view to be rendered.

private readonly IProjectService projectService;
public HomeController(IProjectService projectService)
{
    this.projectService = projectService;
}
public IActionResult Index()
{
    Organization org = projectService.GetOrganization();
    return View(org);
}

If we try to run the application at this point we’ll receive an exception because we haven’t yet added a concrete implementation of ourIProjectService to the DI container.

InvalidOperationException: Unable to resolve service for type 'DependencyInjectionMVC6Demo. Services. IProjectService' while attempting to activate 'DependencyInjectionMVC6Demo. Controllers. HomeController'.
Microsoft. Framework. DependencyInjection. ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)

The exception message shows that the code fails during a call toActivatorUtilities.GetService. This is valuable information because it shows that in MVC6 the DI container is already involved in the controller’s construction. Now we just need to tell the container how to resolve the dependency.

In order to resolve the dependency, we need a concrete implementation ofIProjectService. We’ll add a DemoService class and, for simplicity, it will use static dummy data.

public class DemoService : IProjectService
{
    public string Name { get; } = "Demo";

    public Organization GetOrganization() => new Organization
    {
        Name = this.Name,
        AvatarUrl = $"http://placehold.it/100&text={this.Name}",
        Projects = GetProjects()
    };

private IQueryable<Project> GetProjects() => new List<Project> {
         new Project {
             Id = 0,
             Description = "Test project 0",
             Name = "Test 0",
             Stars = 120
         },
         //...
         new Project {
             Id = 4,
             Description = "Test project 4",
             Name = "Test 4",
             Stars = 89
         }
    }.AsQueryable();
}

Finally, we’ll instruct the DI container to instantiate a new DemoServicewhenever IProjectService is required. To configure the container we’ll modify the ConfigureServices method in Startup.cs. Our configuration will be added to the end of this method.

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    //... other services
    // Add MVC services to the services container.
    services.AddMvc();

    //our services
}

The service is added by using the AddTransient extension method on the services collection, and setting the IProjectService as the type of service and the DemoService as the implementation.

public void ConfigureServices(IServiceCollection services)
{
    //... other services
    // Add MVC services to the services container.
    services.AddMvc();

    //our services
    services.AddTransient<IProjectService, DemoService>();
}

With the service added, DemoService will now be instantiated when the controller is created, and the exception will no longer be thrown.



European ASP.NET MVC Hosting - HostForLIFE.eu :: Tag Helpers in ASP.NET Core

clock September 29, 2016 21:44 by author Scott

What's a Tag Helper?

It's a set of code that allows you to no longer have to use Razor helpers to build your cshtml forms. What this means is that when you had to write this:

@Html.ActionLink("Add a Movie", "Add", "Movie")

You can now write this:

<a asp-action="Add" asp-controller="Movie">Add a Movie</a> 

Because of this, you can now write views that look like HTML rather than an unwieldy mix of HTML and C#.

The Completed Form

I like to show the results first. Here's the view model we will be using:

public class AddMovieVM 
{
    [Required(ErrorMessage = "Please enter a title for this movie.")]
    [Display(Name = "Title:")]
    public string Title { get; set; }

    [Required(ErrorMessage = "Please select a release date for this movie.")]
    [Display(Name = "Release Date:")]
    public DateTime ReleaseDate { get; set; }

    [Required(ErrorMessage = "Please enter a running time for this movie")]
    [Range(1, 1000, ErrorMessage = "The running time must be between 1 and 1000 minutes.")]
    [Display(Name = "Running Time:")]
    public int RunningTime { get; set; }

    [Display(Name = "Description:")]
    public string Description { get; set; }

    [Display(Name = "Genre:")]
    public int SelectedGenre { get; set; }

    public List<SelectListItem> AllGenres { get; set; }
}

Now, if we were using HTML Helpers, our corresponding Add view might look like this:

@model MoreTagHelpers.ViewModels.AddMovieVM

<h2>Add a Movie</h2> 
@Html.ActionLink("Back to Movies", "Add", "Movie")
@using (Html.BeginForm("Add", "Movie"))
{
    <div>
        <div>
            @Html.LabelFor(x=>x.Title)
            @Html.TextBoxFor(x=>x.Title)
            @Html.ValidationMessageFor(x=>x.Title)
        </div>
        <div>
            @Html.LabelFor(x => x.ReleaseDate)
            @Html.TextBoxFor(x => x.ReleaseDate, new { @type = "date" })
            @Html.ValidationMessageFor(x => x.ReleaseDate)
        </div>
        <div>
            @Html.LabelFor(x => x.RunningTime)
            @Html.TextBoxFor(x => x.RunningTime, new { @type = "number" })
            @Html.ValidationMessageFor(x => x.RunningTime)
        </div>
        <div>
            @Html.LabelFor(x => x.Description)
            @Html.TextAreaFor(x => x.Description)
            @Html.ValidationMessageFor(x => x.Description)
        </div>
        <div>
            @Html.LabelFor(x=>x.SelectedGenre)
            @Html.DropDownListFor(x => x.SelectedGenre, Model.AllGenres)
            @Html.ValidationMessageFor(x => x.SelectedGenre)
        </div>
        <div>
            <input type="submit" value="Save" />
        </div>
    </div>
}

Now, here's that same form, using Tag Helpers.

@model MoreTagHelpers.ViewModels.AddMovieVM

<h2>Add a Movie</h2> 
<a asp-action="Index" asp-controller="Movie">Back to Movies</a> 
<form asp-action="Add" asp-anti-forgery="true" asp-controller="Movie"> 
    <div>
        <div>
            <label asp-for="Title"></label>
            <input type="text" asp-for="Title" />
            <span asp-validation-for="Title"></span>
        </div>
        <div>
            <label asp-for="ReleaseDate"></label>
            <input type="date" asp-for="ReleaseDate" />
            <span asp-validation-for="ReleaseDate"></span>
        </div>
        <div>
            <label asp-for="RunningTime"></label>
            <input type="number" asp-for="RunningTime" />
            <span asp-validation-for="RunningTime"></span>
        </div>
        <div>
            <label asp-for="Description"></label>
            <textarea asp-for="Description"></textarea>
            <span asp-validation-for="Description"></span>
        </div>
        <div>
            <label asp-for="SelectedGenre"></label>
            <select asp-for="SelectedGenre" asp-items="Model.AllGenres"></select>
            <span asp-validation-for="SelectedGenre"></span>
        </div>
        <div>
            <input type="submit" value="Save" />
        </div>
    </div>
</form> 

HTML all the things! That second form is much cleaner than the first IMHO. But, what really makes it is that Visual Studio will highlight which HTML tags are using tag helpers:

 

 

The normal HTML is highlighted regularly, and the tag helper HTML is in purple, making it really obvious which is which and hopefully negating some of the complaints I've seen about Razor being more obvious than Tag Helpers.

Let's dive into some of these helpers to see how you can use them in your ASP.NET MVC 6 projects.

Anchor Tag Helper

First, let's look at this helper:

<a asp-action="Index" asp-controller="Movie">Back to Movies</a> 

That's just an anchor tag with two tag helper attributes. Notice that each tag helper attribute begins with "asp-", and their names make intrinsic sense to us: "action" and "controller".

In the particular case of the anchor tag helper, there's a few other properties we could set, like asp-fragment, asp-route, and asp-path. Even better, Visual Studio now gives you intellisense for these attributes:

Form Tag Helper

The form tag helper looks something like this:

<form asp-action="Add" asp-anti-forgery="true" asp-controller="Movie"></form> 

The properties "asp-action" and "asp-controller" are same as in the anchor tag helper, but notice the "asp-anti-forgery" property. Setting this to true is the same as using the @Html.AntiForgeryToken helper in Razor. This helper has simply made your views a little bit cleaner.

Label Tag Helper

Making your views a little bit cleaner is a theme you'll see woven into each of the tag helpers, and the next example comes with the label tag helper. Here's our example:

<label asp-for="Title"></label> 

Input Tag Helper

Continuing with the simple theme:

<input type="text" asp-for="Title" /> 

Now there are many different kinds of input tags (e.g. date, checkbox, text, radio, etc.) and each kind had a different Razor helper. In the new tag helpers, there's just the input tag helper, with two attributes: "asp-for" and "asp-format".

TextArea Tag Helper

The text area is a separate tag in HTML. Here's the helper for it:

<textarea asp-for="Description"></textarea> 

Select Tag Helper

Another tag which is different from the standard input tag is the select tag, and consequently it has a different tag helper:

<select asp-for="SelectedGenre" asp-items="Model.AllGenres"></select> 

Again we see "asp-for" but now we also see the source collection specified using "asp-items." Easy. One odd thing I noticed about this is that "asp-for" doesn't require the Model. prefix, but "asp-items" does. If anybody knows why this is, I'd love to hear it.

Validation Tag Helper

The final tag helper we see on the completed form above is the one on a <span> tag. This is an unusual one, since under many circumstances you won't want to use a span tag as anything other than a <span>.

Except when what you want is a validation message. In that case, you'd use this:

<span asp-validation-for="Description"></span> 

This is the time when we should show the HTML that this renders:

<span class="field-validation-valid" data-valmsg-for="SelectedGenre" data-valmsg-replace="true"></span> 

But wait, that's not all! There are several other helpers we can use.

Environment Tag Helper

Here's one of those other helpers:

<environment names="Development"> 
...
</environment> 
<environment names="Staging,Production"> 
...
</environment> 

This helper is really interesting because the contents of the helper only get rendered if the HTML is deployed into specific environments. It does this by looking at an environment variable called ASPNET_ENV, and which you can set by right-clicking on the Project file and selecting Properties, then selecting Debug.

I'm hoping there's an easier way to change this variable in the fully-released version of Visual Studio, but until then, this is how you use it.

Link and Script Tag Helpers

These are possibly the most interesting new helpers.

<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/3.0.0/css/bootstrap.min.css" 
asp-fallback-href="~/lib/bootstrap/css/bootstrap.min.css" asp-fallback-test-class="hidden" asp-fallback-test-property="visibility" asp-fallback-test-value="hidden" />

<script src="//ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.js" asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js" asp-fallback-test="window.jQuery"></script> 

There's a lot going on here. First, notice the values in the src attribute. Those urls point to the Microsoft Ajax CDN, a new (to me, at least) content-delivery network that holds many commonly-used production CSS and JS files, particularly those produced and maintained by Microsoft. In our case, in the sample project we get the script files for jQuery, unobtrusive validation, bootstrap, and others.

But what about those "asp-fallback-src" attributes? They specify a second location that we can go grab the source files from should the first location be unavailable. In other words, we now have a fallback plan that allows our CSS and JS files to gracefully degrade over should the CDN (if we are using one) not be available. Finally, note that the fallback parameters are entirely optional.

Image Tag Helper

New in the Beta 5 release of ASP.NET is the Image Tag Helper which looks like this:

<img src="~/content/images/profile.jpg" 
     alt="John Smith"
     asp-append-version="true" />

Notice the new asp-append-version attribute; that's the only TagHelper attribute in this tag. What that does is render an <img> with a query string attribute appended on the source URL, like this:

<img src="/content/images/profile.jpg?v=X5q6D366_nQ2fQqUso0F24gWy2ZekXjHz83KmWyaiOOk" 
     alt="company logo"/>

The content of the v attribute is determined by the content of the image; if the content of the image changes, so does the v attribute. This forces the browser to download the image again.

This is a technique known as cache busting; writing code that forces the browser to download a resource (in this case, an image) if that resource changes. This technique guarantees that the user will always get the most recent version of the resource.

Cache Tag Helper

The Cache tag helper is similar to the Environment tag helper in that it doesn't target a specific HTML tag. Rather, it caches its contents in server-side memory, set to an expiration date. An example might look like this:

<cache expires-after="@TimeSpan.FromMinutes(5)" vary-by-user="true"> 
    @Html.Partial("WeatherReport")
</cache> 

In this sample, the WeatherReport partial view will be cached for 5 minutes, and will vary by the user. We can do this to significantly reduce load on the server as all of these requests will be cached server-side.

What actually happens is that ASP.NET generates an ID that is unique to the context of the cached content, which allows you to have multiple <cache> on a single page and not have them interfere with one another.

There are quite a few ways to control how the cache operates. Attributes include expires-after, expires-on, expires-sliding, vary-by-user, vary-by-query, vary-by-route, etc. You can use any combination of vary-by-* attributes on a single cache tag, and doing so modifies the ID that is generated for the cache.

There's one major limitation to this tag: on the back end, it uses a construct called MemoryCache to store the cached content. MemoryCache is limited by the amount of memory available; once there's not enough memory to go around, MemoryCache will purge items until it has the memory necessary. Further, any app pool reset or server shutdown will destroy this cache. Basically, don't treat MemoryCache like a persistent storage solution, because it is not such a thing.



European ASP.NET MVC 5 Hosting - UK :: Creating Custom Scaffold Templates in ASP.NET MVC

clock November 27, 2015 18:59 by author Scott

Microsoft provides a powerful scaffolding engine for models in ASP.NET MVC applications that use Entity Framework. Scaffolding relieves web developers from the mundane task of writing the create, read, update, and delete (CRUD) code over and over again. The scaffolding engine uses T4 templates to generate basic controllers and views for models. However, scaffolded code is just a starting point, since it often needs to be customized to meet specific business requirements or satisfy specific design patterns.

In this blog post, I’ll provide a walkthrough on how to create project-specific custom scaffold templates for ASP.NET MVC. This can be a huge time-saver in applications with a large number of controllers and views. I will use Visual Studio 2013, ASP.NET MVC 5, Entity Framework 6, and C#.

SETUP

To get started, create a new ASP.NET MVC web application and add a simple Product model with the properties shown below and build the project.

namespace CustomScaffoldingDemo.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public bool IsDeleted { get; set; }
        public DateTime CreatedDate { get; set; }
        public DateTime UpdatedDate { get; set; }
    }
}

SCAFFOLDING CONTROLLER AND VIEWS

First, let’s use default templates to scaffold a controller and CRUD views for the Product model so we can review the results. To do so, right-click the Controllers folder in Solution Explorer and click Add New Scaffolded Item. In the Add Scaffold dialog, choose the MVC 5 Controller with views, using Entity Framework. On the Add Controller dialog, create a new data context and choose appropriate options that serve as parameters for the scaffolding engine. Then hit the Add button.

The scaffolding engine will use the default T4 templates to generate code for the controller and five views and add them to the appropriate folders. At this point you have full CRUD functionality for the Product model and can run the application.

As you review the generated code, you may notice that the scaffolding engine is intelligent enough to treat the Product ID properly by not scaffolding the editor for this property on the Create or Edit forms. You may also realize that the default templates do not meet the functional specification or your desired design patterns. For example, you may want to achieve the following:

–  Created Date and Updated Date properties should be set automatically by the system on create or update action respectively, and thus should not be editable on the Create and Edit views.
–  Products should be soft-deleted, so the Delete action of the Product controller must be changed to set the IsDeleted property and updating the Product instead of deleting it from the database. Index action should only return Products with IsDeleted set to false.
–  None of the views should display the IsDeleted property.
–  Views should use @ViewBag.Title as the page header instead of the view name. 
–  You may be using a Unit of Work pattern, so all calls to save changes to the database may need to be tweaked. 

You can manually make changes to the generated code, which has several drawbacks, including:

–  Typically, you would want most, if not all, controllers and views to be consistent across all models in your application. Making similar manual changes to controllers and views for all models is not an efficient approach.
–  When you make changes to a model, you will either have to scaffold these files again and lose your manual changes or manually update all views to match the updated model.

The best way to avoid manual changes and enforce consistency is to customize the scaffold templates.

CUSTOMIZING SCAFFOLD TEMPLATES

The original T4 templates used by the scaffolding engine are located in this folder: %programfiles%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates.

While you can directly edit these templates, this will affect scaffolding for all future projects, which is not recommended. Instead, you can create project-specific copies of these templates so you can customize them. To do so, copy these templates into your MVC project’s CodeTemplates folder, following the same sub-folder structure. You only need to copy either C# or VB.NET templates, based on your project. The template filenames include the language they use. The convention is that the scaffolding engine uses the templates in the CodeTemplates project folder, if one exists, instead of the global templates.

Now you can modify these custom scaffold templates, which would affect scaffolded code only for this project. T4 templates are simply text files and can be edited directly in Visual Studio. Unfortunately, Visual Studio 2013 does not include a good T4 editor—there’s no syntax highlighting or IntelliSense. Fortunately, there are some third party add-on products that provide this functionality. Below is a screenshot of how the templates look in Visual Studio 2013. You can see I modified the header on line 26 to use @ViewBag.Title instead of the view name. 

&lt;#@ template language="C#" HostSpecific="True" #&gt;
&lt;#@ output extension=".cshtml" #&gt;
&lt;#@ include file="Imports.include.t4" #&gt;
@model &lt;#= ViewDataTypeName #&gt;
&lt;#
// The following chained if-statement outputs the file header code and
// markup for a partial view, a view using a layout page, or a regular view.
if(IsPartialView) {
#&gt; 

&lt;#
} else if(IsLayoutPageSelected) {
#&gt; 

@{
    ViewBag.Title = "&lt;#= ViewName#&gt;";
&lt;#
if (!String.IsNullOrEmpty(LayoutPageFile)) {
#&gt;
    Layout = "&lt;#= LayoutPageFile#&gt;";
&lt;#
}
#&g
t;
}

@ViewBag.Title

To learn more about scaffolding check out this walkthrough from Microsoft. To learn more about T4 templates in general, start by reading this MSDN article



About HostForLIFE.eu

HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2012 Hosting, ASP.NET 4.5 Hosting, ASP.NET MVC 5 Hosting, and SQL 2014 Hosting.


Tag cloud

Sign in