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 MVC 4 Hosting - Amsterdam :: Revisiting IBundleTransform ASP.NET 4.5 and MVC 4

clock May 13, 2013 10:26 by author Scott

Web optimization frameworks include two defaults transform type JsMinify and CssMinify which is used by ScriptBundle and StyleBundle respectively. However we can create our own custom transform type to processe references as per our need. To create custom transform type, we need to create class which implements IBundleTransform interface.

IBundleTransform interface define a method named Process which process bundle response. In developer preview version, Process method had only one parameter of type BundleResponse, however onwards RC release, Process method introduced one more parameter of type BundleContext. In this post, we will see how we can utilize this additional parameter while creating our custom transform type.

BundleContext

As name suggest, with BundleContext, we can get information about bundles which could include existing bundle information, bundle url, HTTP context for bundle, etc. Following is the list of all property of BundleContext.

- BundleContext.BundleCollection : We can get collection of all bundles including default and custom bundle in application through this property.

- BundleContext.BundleVirtualPath : This property expose virtual bundle url i.e. ~/bundles/MyBundle.

- BundleContext.HttpContext : This property is type of HttpContextBase, and we can have access of HTTP context through this property. This is very much useful property when we are creating transform type which generate dynamic response. For e.g. we can access query string parameter passed to bundle url (~/bundles/MyBundle?id=123) through this property (context.HttpContext.Request.QueryString["id"]) and we can use it to create dynamic bundle response.

- BundleContext.UseServerCache : Default value of this property is true. It means only first request to bundle url will be intercepted by transform types and once response is generated it will be stored in server cache and further request to bundle url will be served from server cache without processing it. This will help to reduce bundle processing time and to increase performance. If we set BundleContext.UseServerCache to false then all request will be processed by transform type this is only necessary when bundle url are generating dynamic response. See detailed walkthrough later in this post showing how to use this property in accordance with BundleResponse.Cacheability.

- BundleContext.EnableInstrumentation : Default value of this property is false. This is used for tracing and analysis purpose. We can check value of this property and can write tracing code accordingly. We can also set true to this property to enable instrumentation for further lifecycle of Web optimization frameworks for current bundle request.

BundleResponse

BundleResponse is used to retrieve list of files included in bundle so we can process it and generate response for bundle. As BundleResponse is used to generate response of bundles, it needs to take care of two primary properties of generated response. One is response content type and another one is HTTP Cache-Control header. So BundleResponse also expose properties for the same. Following is the list of all properties in BundleResponse class.

- BundleResponse.Files : This is IEnumerable collection of files which is included in bundle. We can iterate through this collection and process file content to generate bundle response.

- BundleResponse.ContentType : Through this property, we can set content type for bundle so that browser can render it appropriately. Default content type "text/html".

- BundleResponse.Cacheability : We can use this property to set Cache-Control HTTP header of bundled response. Default value of this property is Public.

- BundleResponse.Content : Anything which we set as a value of this property, that content will be sent back to browser as a response of bundle.

Following is the complete code which shows how to create custom transform type and how we can use it with bundling.

public class CustomTransformType : IBundleTransform
{
    public void Process(BundleContext context, BundleResponse response)
    {
        string strBundleResponse = string.Empty;
        foreach (FileInfo file in response.Files)
        {
            // PROCESS FILE CONTENT
        }
        response.Content = strBundleResponse;
    }


Bundle myBundle = new Bundle("~/bundles/MyBundle", new CustomTransformType());
myBundle.Include("~/path/to/file");
bundles.Add(myBundle);

Bundle and truly dynamic response

As we noted earlier, we can set BundleContext.UseServerCache to false in order to process all bundle request and generate dynamic response. Let try to simulate this by small walkthrough and see it works or we need to take care any additional parameter.

public void Process(BundleContext context, BundleResponse response)

{
    context.UseServerCache = false;
    response.Content = DateTime.Now.ToString();
}


We are returning current date time with UseServerCache set to false. Now try to hit bundle url multiple times by pressing F5. Oops… it seems it has processed bundle response only first time. Let dig more into this, open another browser and hit same url… ahmm it seems it has processed bundle response one more time… again press F5 multiple times…bad luck

As we can see, it seems (read again it seems) it is processing bundle response only first time for separate client (is it really? nop). Nop this is not the case. In fact this is how client deals with it due to HTTP cache control header. Confused? See response header of bundle url to get more information.

As we noted earlier default value of BundleResponse.Cacheability is Public. So even if we have set BundleContext.UseServerCache to false then also due to Expires response header and Public Cache-Control header client is not sending request back to server. So in this case we need to also set BundleResponse.Cacheability to NoCache. We can also set it to Private but in some client we need to press Ctrl + F5 to refresh bundle response.

public void Process(BundleContext context, BundleResponse response)
{
    context.UseServerCache = false;
    response.Cacheability = HttpCacheability.NoCache;
    response.Content = DateTime.Now.ToString();
}

After setting BundleResponse.Cacheability to NoCache try to refresh bundle url again now it is re generating bundle response on each request.



European ASP.NET MVC 4 Hosting - Amsterdam :: Create SignalR with ASP.NET MVC 4

clock May 6, 2013 06:36 by author Scott

This is a simple tutorial for you how to get Signal R running in a MVC project via Visual Studio and the NuGet package manager console. OK, here we go:

1. Create a new MVC project called "MySignalR" ( either 3 or 4, and either an empty project or a templated project ). I will choose the Empty project for mine.

2. Via the NuGet package manager console, type

Install-Package SignalR

This will add all the necessary files to your project (SignalR assemblies, Newtonsoft assembly, and various javascript files required). If you don't have NuGet installed in your visual studio, then visit this site for more information on how to install http://nuget.codeplex.com/wikipage?title=Getting%20Started

3. Create a Hub to which will be your message "router". So create a new class, "SNLR.cs" and add the following code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using SignalR;
    using SignalR.Hubs;
    namespace MySignalR
    {
    public class SNRL : Hub
    {
    public void SendMessage(string msg)
    {
    Clients.sendMessage(msg);
    }
    }
    }

4. If you have chosen the Empty project, then you will need to create a "Shared" folder within your "Views" folder. Within this, then create a new View called "_Layout.cshtml". This will be the layout for your page and will reference all the Javascript files needed.

Once you have created your _Layout page, add a link to the following javascript files, so your page looks like this:

    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>_Layout</title>
    </head>

    <body>
        <div>       
            @RenderBody()
        </div>
        <script src="~/Scripts/jquery-1.6.4.min.js"></script>
        <script src="~/Scripts/jquery.signalR-0.5.3.min.js"></script>
        <script src="~/signalr/hubs"></script>
    @RenderSection("JavaScript", false)
    </body>
    </html>

5. Add a file called "_ViewStart.cshtml" on your Views folder and add the following code:

    @{
        Layout = "~/Views/Shared/_Layout.cshtml";
    }

6. Create a new Empty Controller in your Controllers folder and name it "Home". This will generate the "Index" ActionResult, so then right click on the word "View();" and select "Add View" making sure that you have "User a layout or master page:" selected.

Add the following code to this newly created "Index.cstml" page:

    @{
        ViewBag.Title = "Index";
    }
    <h2>Index</h2>
    <span id="mySpanTag"></span>
    @section JavaScript{
        <script>
            $(function () {
                var myHub = $.connection.sNRL;
                myHub.sendMessage = function (data) {
                    $('#mySpanTag').html(data);
                };
                $.connection.hub.start(function () {
                    myHub.sendMessage("Hello World!");
                });
            });
        </script>
    }

7. Run the project. You will see the phrase "Hello World" on the screen. This has been sent from our JavaScript code to our SNLR Hub and then sent back to our JavaScript code, which then renders it on the page. Simples!

Once you have mastered the basics, you can then look into sending messages from the Hub to only the person requesting the data, or groups of users.

Hope you enjoy the tutorial. You can apply this new features. Find more about ASP.NET MVC 4 hosting on HostForLIFE.eu.

 



European ASP.NET MVC 4 Hosting - Amsterdam :: How to Upload a file in MVC4 C#5 .NET 4.5

clock May 3, 2013 06:33 by author Scott

One of the features of this so called killer app will be to upload pictures (nothing special I agree). But how would I do this for all the clients I hope to support (WinRT/WP7/Html5/IOS).

Let me first present the server that will be used for all these clients, I’ll then follow up with what I consider to be the simplest client a html5 browser!

Server

So I fired up VS11 and created a new MVC4 application using .net 4.5 / C#  and the WebApi template.

I then added a controller called FileUploadController.cs

   1:  using System.Collections.Generic;
   2:  using System.Linq;
   3:  using System.Net;
   4:  using System.Net.Http;
   5:  using System.Threading.Tasks;
   6:  using System.Web.Http;
   7:   
   8:  namespace MvcApplication16.Controllers
   9:  {
  10:      public class FileUploadController : ApiController
  11:      {
  12:          public async Task<IEnumerable<string>> PostMultipartStream()
  13:          {
  14:              // Check we're uploading a file
  15:              if (!Request.Content.IsMimeMultipartContent("form-data"))           
  16:                  throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
  17:                 
  18:              // Create the stream provider, and tell it sort files in my c:\temp\uploads folder
  19:              var provider = new MultipartFormDataStreamProvider("c:\\temp\\uploads");
  20:   
  21:              // Read using the stream
  22:              var bodyparts = await Request.Content.ReadAsMultipartAsync(provider);           
  23:          
  24:              // Create response.
  25:              return provider.BodyPartFileNames.Select(kv => kv.Value);           
  26:          }
  27:      }
  28:      
  29:  }

You can see from line 12 that I’ve made this operation async, you’ve really got to admire the simplicity of async/await construct in .net 4.5! In line 22 you can see that the compiler and some state machine magic allow the freeing up of the asp worker thread…..

HTML5 Client

The client couldn’t have been easier, fist a look at it in the browser

   7:      <meta name="viewport" content="width=device-width" />
   8:  </head>
   9:  <body>
  10:      @using (Html.BeginForm("FileUpload", "api", FormMethod.Post, new { enctype = "multipart/form-data" }))
  11:      {
  12:          <div>Please select some files</div>
  13:          <input name="data" type="file" multiple>
  14:          <input type="submit" />           
  15:      }
  16:  </body>
  17:  </html>

The important part above is using the enctype attribute, in fact line 10 loosely translates to

<form action="~/api/FileUpload" enctype="multipart/form-data" method="POST">

Don’t believe me? Then try VS11’s awesome new feature – page inspector

Right click on the html and choose view in page inspector

and we’re done! Of course in the real world we’ll use ajax with a few trick re sandbox, but here’s the response in the browser with xml.

I’ll hopefully follow up with the samples for the client list below when I get to the respective development machines.

 



European ASP.NET MVC 4 Hosting - Amsterdam :: Using MySql 5 as Membership Backend for ASP.NET 4.5 MVC 4 Application

clock May 1, 2013 09:18 by author Scott

Oracle provide MySql ASP.Net web providers through NuGet – search for MySql.Web. Using the MySql providers you can easily use MySql as your membership/profile/role backend for an ASP.Net application.

I am going to demonstrate using it as the membership provider for an MVC 4 application using Razor but the steps are almost identical for the ASPX views.

Web.config for MySql Membership Provider

Use the following configuration in your web.config file:

1              <membership defaultProvider="MySqlMembershipProvider">
2              <providers>
3              <clear />
4              <add name="MySqlMembershipProvider" type="MySql.Web.Security.MySQLMembershipProvider, MySql.Web, Version=6.5.4.0, PublicKeyToken=c5687fc88969c44d"
5              autogenerateschema="true"
6              connectionStringName="*NAME_OF_YOUR_CONN_STRING*"
7              enablePasswordRetrieval="false"
8              enablePasswordReset="true"
9              requiresQuestionAndAnswer="false"
10           requiresUniqueEmail="false"
11           passwordFormat="Hashed"
12           maxInvalidPasswordAttempts="5"
13           minRequiredPasswordLength="6"
14           minRequiredNonalphanumericCharacters="0"
15           passwordAttemptWindow="10"
16           passwordStrengthRegularExpression=""
17           applicationName="/" />
18           </providers>
19           </membership>

Obviously you also need to configure a valid MySql connection string, create a MySql schema, change any other security settings you want and put the name of your connection string into the provider configuration but your on your own doing that.

Create Tables

Once you have the initial setup done open the ASP.Net configuration website (VS2012: Project menu -> ASP.NET Configuration – at the bottom of the menu) and create a user in the security tab. Doing this will create the database structure and a new user providing you have set the configuration up correctly.

Unbreak the MVC 4 AccountController

This is a simple fix for getting MySql up and running. Basically we just rollback the AccountController to use the old style MembershipProvider which is supported by the MySql MembershipProvider.

  1. Delete the MVC 4 AccountController, AccountModels, Account view folder and _LoginPartial shared view
  2. Create a new MVC 3 web application
  3. Copy the MVC 3 AccountController, AccountModels, Account view folder and _LogOnPartial shared view into your MVC 4 application
  4. Replace @Html.Partial(“_LoginPartial”) in the shared _Layout view with @Html.Partial(“_LogOnPartial”)

This won’t support OAuth authentication but will get your MySql Membership provider up and running with ASP.Net 4.5 and MVC 4.

Raw SQL for MySql Membership Tables

If you want to directly create the membership data structure without using the ASP.NET configuration tools use the following SQL as a base and modify SCHEMA_NAME and collation to be what you require.

1              -- -----------------------------------------------------
2              -- Table `SCHEMA_NAME`.`my_aspnet_applications`
3              -- -----------------------------------------------------
4              CREATE  TABLE IF NOT EXISTS `SCHEMA_NAME`.`my_aspnet_applications` (
5                `id` INT(11) NOT NULL AUTO_INCREMENT ,
6                `name` VARCHAR(256) NULL DEFAULT NULL ,
7                `description` VARCHAR(256) NULL DEFAULT NULL ,
8                PRIMARY KEY (`id`) )
9              ENGINE = InnoDB
10           AUTO_INCREMENT = 2
11           DEFAULT CHARACTER SET = latin1
12           COLLATE = latin1_swedish_ci;
13           -- -----------------------------------------------------
14           -- Table `SCHEMA_NAME`.`my_aspnet_membership`
15           -- -----------------------------------------------------
16           CREATE  TABLE IF NOT EXISTS `SCHEMA_NAME`.`my_aspnet_membership` (
17             `userId` INT(11) NOT NULL DEFAULT '0' ,
18             `Email` VARCHAR(128) NULL DEFAULT NULL ,
19             `Comment` VARCHAR(255) NULL DEFAULT NULL ,
20             `Password` VARCHAR(128) NOT NULL ,
21             `PasswordKey` CHAR(32) NULL DEFAULT NULL ,
22             `PasswordFormat` TINYINT(4) NULL DEFAULT NULL ,
23             `PasswordQuestion` VARCHAR(255) NULL DEFAULT NULL ,
24             `PasswordAnswer` VARCHAR(255) NULL DEFAULT NULL ,
25             `IsApproved` TINYINT(1) NULL DEFAULT NULL ,
26             `LastActivityDate` DATETIME NULL DEFAULT NULL ,
27             `LastLoginDate` DATETIME NULL DEFAULT NULL ,
28             `LastPasswordChangedDate` DATETIME NULL DEFAULT NULL ,
29             `CreationDate` DATETIME NULL DEFAULT NULL ,
30             `IsLockedOut` TINYINT(1) NULL DEFAULT NULL ,
31             `LastLockedOutDate` DATETIME NULL DEFAULT NULL ,
32             `FailedPasswordAttemptCount` INT(10) UNSIGNED NULL DEFAULT NULL ,
33             `FailedPasswordAttemptWindowStart` DATETIME NULL DEFAULT NULL ,
34             `FailedPasswordAnswerAttemptCount` INT(10) UNSIGNED NULL DEFAULT NULL ,
35             `FailedPasswordAnswerAttemptWindowStart` DATETIME NULL DEFAULT NULL ,
36             PRIMARY KEY (`userId`) )
37           ENGINE = InnoDB
38           DEFAULT CHARACTER SET = latin1
39           COLLATE = latin1_swedish_ci
40           COMMENT = '2';
41           -- -----------------------------------------------------
42           -- Table `SCHEMA_NAME`.`my_aspnet_profiles`
43           -- -----------------------------------------------------
44           CREATE  TABLE IF NOT EXISTS `SCHEMA_NAME`.`my_aspnet_profiles` (
45             `userId` INT(11) NOT NULL ,
46             `valueindex` LONGTEXT NULL DEFAULT NULL ,
47             `stringdata` LONGTEXT NULL DEFAULT NULL ,
48             `binarydata` LONGBLOB NULL DEFAULT NULL ,
49             `lastUpdatedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ,
50             PRIMARY KEY (`userId`) )
51           ENGINE = InnoDB
52           DEFAULT CHARACTER SET = latin1
53           COLLATE = latin1_swedish_ci;
54           -- -----------------------------------------------------
55           -- Table `SCHEMA_NAME`.`my_aspnet_roles`
56           -- -----------------------------------------------------
57           CREATE  TABLE IF NOT EXISTS `SCHEMA_NAME`.`my_aspnet_roles` (
58             `id` INT(11) NOT NULL AUTO_INCREMENT ,
59             `applicationId` INT(11) NOT NULL ,
60            `name` VARCHAR(255) NOT NULL ,
61             PRIMARY KEY (`id`) )
62           ENGINE = InnoDB
63           DEFAULT CHARACTER SET = latin1
64           COLLATE = latin1_swedish_ci
65           ROW_FORMAT = DYNAMIC;
66           -- -----------------------------------------------------
67           -- Table `SCHEMA_NAME`.`my_aspnet_schemaversion`
68           -- -----------------------------------------------------
69           CREATE  TABLE IF NOT EXISTS `SCHEMA_NAME`.`my_aspnet_schemaversion` (
70             `version` INT(11) NULL DEFAULT NULL )
71           ENGINE = InnoDB
72           DEFAULT CHARACTER SET = latin1
73           COLLATE = latin1_swedish_ci;
74           -- -----------------------------------------------------
75           -- Table `SCHEMA_NAME`.`my_aspnet_sessioncleanup`
76           -- -----------------------------------------------------
77           CREATE  TABLE IF NOT EXISTS `SCHEMA_NAME`.`my_aspnet_sessioncleanup` (
78             `LastRun` DATETIME NOT NULL ,
79             `IntervalMinutes` INT(11) NOT NULL )
80           ENGINE = InnoDB
81           DEFAULT CHARACTER SET = latin1
82           COLLATE = latin1_swedish_ci;
83           -- -----------------------------------------------------
84           -- Table `SCHEMA_NAME`.`my_aspnet_sessions`
85           -- -----------------------------------------------------
86           CREATE  TABLE IF NOT EXISTS `SCHEMA_NAME`.`my_aspnet_sessions` (
87             `SessionId` VARCHAR(255) NOT NULL ,
88             `ApplicationId` INT(11) NOT NULL ,
89             `Created` DATETIME NOT NULL ,
90             `Expires` DATETIME NOT NULL ,
91            `LockDate` DATETIME NOT NULL ,
92             `LockId` INT(11) NOT NULL ,
93             `Timeout` INT(11) NOT NULL ,
94             `Locked` TINYINT(1) NOT NULL ,
95             `SessionItems` LONGBLOB NULL DEFAULT NULL ,
96             `Flags` INT(11) NOT NULL ,
97             PRIMARY KEY (`SessionId`, `ApplicationId`) )
98           ENGINE = InnoDB
99           DEFAULT CHARACTER SET = latin1
100         COLLATE = latin1_swedish_ci;
101         -- -----------------------------------------------------
102         -- Table `SCHEMA_NAME`.`my_aspnet_users`
103         -- -----------------------------------------------------
104         CREATE  TABLE IF NOT EXISTS `SCHEMA_NAME`.`my_aspnet_users` (
105           `id` INT(11) NOT NULL AUTO_INCREMENT ,
106           `applicationId` INT(11) NOT NULL ,
107          `name` VARCHAR(256) NOT NULL ,
108           `isAnonymous` TINYINT(1) NOT NULL DEFAULT '1' ,
109           `lastActivityDate` DATETIME NULL DEFAULT NULL ,
110           PRIMARY KEY (`id`) )
111         ENGINE = InnoDB
112         AUTO_INCREMENT = 2
113         DEFAULT CHARACTER SET = latin1
114         COLLATE = latin1_swedish_ci;
115         -- -----------------------------------------------------
116         -- Table `SCHEMA_NAME`.`my_aspnet_usersinroles`
117         -- -----------------------------------------------------
118         CREATE  TABLE IF NOT EXISTS `SCHEMA_NAME`.`my_aspnet_usersinroles` (
119           `userId` INT(11) NOT NULL DEFAULT '0' ,
120           `roleId` INT(11) NOT NULL DEFAULT '0' ,
121           PRIMARY KEY (`userId`, `roleId`) )
122         ENGINE = InnoDB
123         DEFAULT CHARACTER SET = latin1
124         COLLATE = latin1_swedish_ci
125         ROW_FORMAT = DYNAMIC;

 



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 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in