Server side resource rendering with Angular and ASP .NET MVC: pass data from html to controller.

I wanted a ASP .NET MVC view (*.cshtml) to render on the server and pass the static text contained in the the ASP .NET project resource file to an Angular controller, so on the initial page request, all static data is returned to the client. Dynamic data, like grid content would then be requested by a separate JSON call.

The resource data is passed to the Angular controller by using ng-init.

 

For the sake of this blog post I stuffed everything in one *.cshtml page, including CSS en JavaScript.

Of course this would be separate files in an real application.

 

Project resource file

image

 

Layout.cshtml

 

<!DOCTYPE html> <html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="app"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Send initialization data from HTML to Angular controller</title> <style> /* Add some initial styling. */ html, body { background-color: #F1F1F1; font-family: "Open Sans", sans-serif; font-size: 13px; height: 100%; } body { margin: 20px; } [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; } </style> <!-- Library scripts --> <script src="https://code.angularjs.org/1.4.1/angular.min.js"></script> </head> <body ng-cloak> @RenderBody() <div> <div ng-controller="main" ng-init="resources={ textFromResource: '@WebApplication1.Properties.Resources.TextFromResource'}"> <h1>{{ title }}</h1> {{ resources.textFromResource }} </div> </div> <script> // Angular module. (function () { "use strict"; angular .module("app", []); }()); // Angular controller. (function () { "use strict"; function controller($scope) { $scope.title = "Show ASP .NET MVC resoure (*.resx) data to user on initial load."; } angular .module("app") .controller("main", ["$scope", controller]); }()); </script> </body> </html>

 

 

Result

image

Post arbitrary JSON data to a MVC controller action method

If you want to sent arbitrary JSON data to a MVC controller action method, you can use the following code:

[HttpPost]
public ActionResult HandleRequest()
{
    // Read the RAW JSON from the request, 
    // because MVC does not support a dynamic input parameter or an input parameter of type JObject.
    // ASP .NET Web API does support a dynamic input parameter or an input parameter of type JObject.
    string json = new StreamReader(this.Request.InputStream).ReadToEnd();
    dynamic clientData = JObject.Parse(json);

Using ValidateAntiForgeryToken with AngularJS and MVC

I was getting a HTTP 500 error, when posting data from AngularJS to a MVC controller, which had the attribute ValidateAntiForgeryToken applied to it. This attribute expects a form to be posted to the MVC controller action method, but I wanted to sent JSON. If you want to do that then you can follow the blogpost from julian jelfs.

 

Now I just add: @Html.AntiForgeryToken()

Then I apply the custom attribute ValidateJsonAntiForgeryToken to the MVC controller action method, like

[HttpPost]
[Authorize] [ValidateJsonAntiForgeryToken]
public ActionResult GetDashboardData(DashboardViewModel model) {

Now I can Post data in AngularJS like:

// When using the @Html.AntiForgeryToken() and [ValidateJsonAntiForgeryToken], a http POST, 
// should contain a AntiForgeryToken in the header. // The @Html.AntiForgeryToken() will write add a hidden HTML input element with the name
//"__RequestVerificationToken". // This input element will contain to AntiForgeryToken. // The MVC AuthorizeAttribute [ValidateJsonAntiForgeryToken],
//will check the http request header for the "AntiForgeryToken".
function getHttpConfig() { var token = angular.element("input[name='__RequestVerificationToken']").val(); var config = { headers: { '__RequestVerificationToken': token } }; return config; }

var config = getHttpConfig();
var url = “http://localhost”;
var postData = {}; return $http.post(url, postData, config).then(function (response) {
// Do something terrible
});

 

Solution

 

https://julianjelfs.wordpress.com/category/mvc/

Manually create the SQL Server tables used by de SimpleMembershipProvider

 

Below you will find the t-sql code needed to generate de SQL Server SimpleMembershipProvider tables.

 

 

set ansi_nulls on
go
set quoted_identifier on
go

if object_id('dbo.webpages_Membership') is null
begin
    create table dbo.webpages_Membership
    (
        UserId                                    int not null constraint PK_Membership_UserId primary key,
        CreateDate                                datetime null,
        ConfirmationToken                        nvarchar(128) null,
        IsConfirmed                                bit null constraint DF_Membership_IsConfirmed default (0),
        LastPasswordFailureDate                    datetime null,
        PasswordFailuresSinceLastSuccess        int not null constraint DF_Membership_PasswordFailuresSinceLastSuccess default (0),
        [Password]                                nvarchar(128) not null,
        PasswordChangedDate                        datetime null,
        PasswordSalt                            nvarchar(128) not null,
        PasswordVerificationToken                nvarchar(128) null,
        PasswordVerificationTokenExpirationDate    datetime null
    )
end
go
set ansi_nulls on
go
set quoted_identifier on
go

if object_id('dbo.webpages_Roles') is null
begin
    create table dbo.webpages_Roles
    (
        RoleId int identity(1,1) not null,
        RoleName nvarchar(256) not null,
        constraint PK_Roles_RoleId primary key clustered 
        (
            RoleId ASC
        ) with (pad_index = off, statistics_norecompute = off, ignore_dup_key = off, allow_row_locks = on, allow_page_locks = on) on [PRIMARY],
        constraint UQ_Roles_RoleName unique nonclustered 
        (
            RoleName asc
        ) with (pad_index = off, statistics_norecompute = off, ignore_dup_key = off, allow_row_locks = on, allow_page_locks = on) on [PRIMARY]
    )
end
go
set ansi_nulls on
go
set quoted_identifier on
go

if object_id('dbo.webpages_OAuthMembership') is null
begin
    create table dbo.webpages_OAuthMembership
    (
        Provider        nvarchar(30) not null,
        ProviderUserId    nvarchar(100) not null,
        UserId            int not null,
        constraint PK_OAuthMembership_Provider_ProviderUserId primary key clustered 
        (
            Provider asc,
            ProviderUserId asc
        ) with    (    pad_index = off, 
                    statistics_norecompute = off,
                    ignore_dup_key = off,
                    allow_row_locks = on,
                    allow_page_locks = on) on [PRIMARY]
    )
end
go
set ansi_nulls on
go
set quoted_identifier on
go

if object_id('dbo.webpages_UserProfile') is null
begin
    create table dbo.webpages_UserProfile
    (
        UserId int identity(1,1) not null,
        UserName nvarchar(56) not null,
        constraint PK_UserProfile_UserId primary key clustered 
        (
            UserId asc
        ) with (pad_index = off, statistics_norecompute = off, ignore_dup_key = off, allow_row_locks = on, allow_page_locks = on) on [PRIMARY],
        constraint UQ_UserProfile_UserName unique nonclustered 
        (
            UserName asc
        ) with (pad_index = off, statistics_norecompute = off, ignore_dup_key = off, allow_row_locks = on, allow_page_locks = on) on [PRIMARY]
    )
end
go
set ansi_nulls on
go
set quoted_identifier on
go

if object_id('dbo.webpages_UsersInRoles') is null
begin
    create table dbo.webpages_UsersInRoles
    (
        UserId int not null constraint FK_UsersInRoles_UserId foreign key(UserId) references dbo.webpages_UserProfile (UserId),
        RoleId int not null constraint FK_UsersInRoles_RoleId foreign key(RoleId) references dbo.webpages_Roles (RoleId),
        primary key clustered 
        (
            UserId asc,
            RoleId asc
        ) with (pad_index = off, statistics_norecompute = off, ignore_dup_key = off, allow_row_locks = on, allow_page_locks = on) on PRIMARY]
    )
end
go

ASP .NET MVC4 / Web Api – Create users and roles for SimpleMembershipProvider with PowerShell and C#

If you are using the SimpleMembershipProvider for FormAuthentication in a ASP .NET MVC4 / Web Api project, the following PowerShell / C# code can be used to create and delete users and roles.

  • Create an empty XML App.config file "C:\Temp\App.config".
  • Paste the XML below in the file and save it.
  • Create an empty PowerShell file "C:\Temp\Manage_MVC_users_and_roles.ps1".
  • Paste the PowerShell code below in the file and save it.
  • Create an empty C# file "C:\Temp\Manage_MVC_users_and_roles.cs".
  • Paste the C# code below in the file and save it.
  • Execute the file "C:\Temp\Manage_MVC_users_and_roles.ps1" with PowerShell.

 

This will create an user "test2" with password "test2" and a role "Administrators".

 

Note

  • Database tables will automatically be created if they don’t exist.
  • De folder "C:\Temp" should contain the assemblies "System.Web.WebPages.dll" and "WebMatrix.Data.dll" and "WebMatrix.WebData.dll", this assembly can be downloaded using NuGet.

App.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <profile defaultProvider="SimpleProfileProvider">
      <providers>
        <add name="SimpleProfileProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"
            connectionStringName="DefaultConnection" applicationName="/" />
      </providers>
    </profile>
    <membership defaultProvider="SimpleMembershipProvider">
      <providers>
        <add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
      </providers>
    </membership>
    <roleManager enabled="true" defaultProvider="SimpleRoleProvider">
      <providers>
        <add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
      </providers>
    </roleManager>
  </system.web>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    </assemblyBinding>
  </runtime>
</configuration>

PowerShell code (Manage_MVC_users_and_roles.ps1)

 
# Get folder containing this script.
$scriptFolder = split-path $SCRIPT:MyInvocation.MyCommand.Path -parent

# Load App.config file from scriptfolder.
$appConfigPath = "$scriptFolder\App.config"
[System.AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", $appConfigPath)

# Compile C# code to dll.
$Assem = ( 
    "WebMatrix.Data", 
    "WebMatrix.WebData",
    "System.Security",
    "System.Web",
    "System.Web.WebPages",
    'System.Web.ApplicationServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
    'System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
)
$codePath = "$scriptFolder\Manage_MVC_users_and_roles.cs"
$codeAssemblyName = "Manage_MVC_users_and_roles.dll"
Add-Type -OutputType Library –ReferencedAssemblies $Assem -OutputAssembly $codeAssemblyName -Path $codePath

# Load dll.
$codeAssemblyPath = "$scriptFolder\$codeAssemblyName"
Add-Type -Path $codeAssemblyPath

# Execute C# code.
$wrapper = New-Object Research.Rli.WebSecurityExecuter
$wrapper.Execute($scriptFolder);

pause
 

C# code

How to make Entity Framework 5.0 use an in-memory persistence DbContext instead of accessing the database.

If you want to switch between in-memory stub data and a database during runtime with Entity Framework 5.0, you have several options, some of them are:

– Using a second level cache mechanism like http://www.codeproject.com/Articles/435142/Entity-Framework-Second-Level-Caching-with-DbConte , filling the cache before use and setting the expiration time to infinite.

– Creating a extension method on the DbSet class that uses only the DbSet (for direct database access) or DbSet.Local for in-memory stub data, based on some parameter.

– Implement a MemoryPersistenceDbContext and MemoryPersistenceDbSet.

 

This post will focus on the last option.

Create a new MVC4 project in Microsoft Visual Studio 2010

File > New > Project

image

 

image

image

 

Add Entity Framework 5.0 NuGet package

Rightclick solution > Manage NuGet Packages for Solution…

image

image

image

image

 

I added 2 tables to a Research database on a LocalDb SQL Server 2012 instance

image

Add *.edmx model

Right click on the models folder:

image

 

image

ModelName = ResearchModel.edmx

image

DbContext name = ResearchUow

(UOW = Unit of work)

image

image

Model namespace = ResearchModel

Check all tables

image

Add code generation item

Open the ResearchUow.edmx > right click > Add Code Generation Item…

image

Code generation item name = ResearchModel.tt

image

Now the project looks like

image

 

Add an IEntity interface

This interface will be used to make the Find function work.

image

Add a MemoryPersistenceDbSet.cs in the Models folder

This will be used to store the data in-memory instead of in the database.

image

Change the ResearchModel.tt file, so all generated POCO entities derive from IEntity

Open the ResearchModel.tt files and change the line

<#=codeStringGenerator.EntityClassOpening(entity)#>

to

<#=codeStringGenerator.EntityClassOpening(entity)#> : IEntity

and click save, on save of the ResearchModel.tt file, the POCO entities will be regenerated and will now all implement the IEntity interface:

image

 

Change the ResearchModel.Context.tt file, so the IResearchUow interface, the ResearchUow class and the MemoryPersistenceResearchUow will be created.

 

Open the ResearchModel.Context.tt file and find the code:


<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext

{

    public <#=code.Escape(container)#>()

        : base("name=<#=container.Name#>")

    {

<#

if (!loader.IsLazyLoadingEnabled(container))

{

#>

        this.Configuration.LazyLoadingEnabled = false;

<#

}

#>

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)

    {

        throw new UnintentionalCodeFirstException();

    }

<#

    foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())

    {

#>

    <#=codeStringGenerator.DbSet(entitySet)#>

<#

    }

    foreach (var edmFunction in container.FunctionImports)

    {

        WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: false);

    }

#>

}

<#

if (!String.IsNullOrEmpty(codeNamespace))

{

    PopIndent();

#>

}

<#

}

#>

 

 

Replace by

 


<#=Accessibility.ForType(container)#> partial interface IResearchlUow

{

<#

    foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())

    {

#>

    <#=codeStringGenerator.IDbSet(entitySet)#>

<#

    }

    foreach (var edmFunction in container.FunctionImports)

    {

        WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: false);

    }

#>

    int SaveChanges();

}

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext, IResearchUow

{

<#

    foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())

    {

#>

    <#=codeStringGenerator.DbSet(entitySet)#>

<#

    }

    foreach (var edmFunction in container.FunctionImports)

    {

        WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: false);

    }

#>

    public <#=code.Escape(container)#>() : base("name=<#=container.Name#>")

    {

<#

if (!loader.IsLazyLoadingEnabled(container))

{

#>

        this.Configuration.LazyLoadingEnabled = false;

<#

}

#>

    }

    public <#=code.Escape(container)#>(string connection) : base(connection)

    {

<#

if (!loader.IsLazyLoadingEnabled(container))

{

#>

        this.Configuration.LazyLoadingEnabled = false;

<#

}

#>

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)

    {

        throw new UnintentionalCodeFirstException();

    }

}

<#=Accessibility.ForType(container)#> partial class MemoryPersistenceResearchUow : <#=code.Escape(container)#>

{

    public MemoryPersistenceResearchUow()

    {

        Seed();

    }

    public void ClearAll()

    {

<#

    foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())

    {

#>

        <#=codeStringGenerator.DbSetInConstructor(entitySet)#>

<#

    }

#>

    }

    public override int SaveChanges()

    {

        return 0;

    }

}

<#

if (!String.IsNullOrEmpty(codeNamespace))

{

    PopIndent();

#>

}

<#

}

#>

 

and find

public string DbSet(EntitySet entitySet)

{

    return string.Format(

        CultureInfo.InvariantCulture,

        "{0} DbSet<{1}> {2} {{ get; set; }}",

        Accessibility.ForReadOnlyProperty(entitySet),

        _typeMapper.GetTypeName(entitySet.ElementType),

        _code.Escape(entitySet));

}

 

Replace by

    public string IDbSet(EntitySet entitySet)

    {

        return string.Format(

            CultureInfo.InvariantCulture,

            "IDbSet<{0}> {1} {{ get; set; }}",

            _typeMapper.GetTypeName(entitySet.ElementType),

            _code.Escape(entitySet));

    }

    public string DbSet(EntitySet entitySet)

    {

        return string.Format(

            CultureInfo.InvariantCulture,

            "{0} IDbSet<{1}> {2} {{ get; set; }}",

            Accessibility.ForReadOnlyProperty(entitySet),

            _typeMapper.GetTypeName(entitySet.ElementType),

            _code.Escape(entitySet));

    }

    public string DbSetInConstructor(EntitySet entitySet)

    {

        return string.Format(

            CultureInfo.InvariantCulture,

            "this.{0} = new MemoryPersistenceDbSet<{0}>();",

            _typeMapper.GetTypeName(entitySet.ElementType));

    }

 

Now on save of the ResearchModel.Context.tt  T4 template will generate the following code:

 

Add a partial class file for the MemoryPersistenceResearchUow

Every time you update the ReserachModel.edmx from the database or save the T4 templates ResearchModel.tt and ResearchModel.Context.tt, the T4 templates will execute and regenerate all POCO entities and the IResearchUow interface, ResearchUow class and the MemoryPersistenceResearchUow.  To prevent the code that seeds the in-memory UOW to be overwritten a partial class MemoryPersistenceResearchUow is created.

image

Add a IResearchUowFactory and ResearchUowFactory that will contain the logic to create a ResearchUow or an MemoryPersistenceResearchUow.

 

The project will no look like:

image

 

Add appSetting "UseStubs" to the Web.config

Install an IoC container by using NuGet, in this case I will use ninject:

Install Ninject and Ninject.MVC3 (no MVC4 available yet, but works just fine) this will also install Ninject.Web.Common.

image

In the App_Start folder change the NinjectWebCommon.cs

Fill the RegisterService function:

In the Controllers folder change the HomeControler, add:

Result

This results in:

image

 

The text "First person name [Roel van Lisdonk]" is shown. This was the data from the seed method:

this.Person.Add(new Person { Id = 1, Name = "Roel van Lisdonk" });

and not from the real database, because the database at this point is empty.

This proves we can switch using in-memory stub data or the real database by changing a appSetting in the web.config.

 

 

 

Don’t forget to fix the unit tests.

In the unit tests for the HomeController, change the lines:

to

 

 

Now you are able to use the ResearchUow within your HomeController and switch between the MemoryPersistenceResearchUow and the ResearchUow by changing the appSetting UseStubs.