Windows 2012 Hosting - MVC 6 and SQL 2014 BLOG

Tutorial and Articles about Windows Hosting, SQL Hosting, MVC Hosting, and Silverlight Hosting

ASP.NET MVC - ASPHostPortal.com :: Internet & Web How to Fix Only One <configSections> Element Error in Web.Config

clock April 11, 2016 19:44 by author Armend

In this article you will learn the solution to the common error "Only one <configSections> element allowed".
Today I was working on Entity Framework and trying to add the connection string to the Web.Config to specify the database. I wrote the connection string like this: 

  <?xml version="1.0" encoding="utf-8"?>     
    <configuration>   
       <connectionStrings>  
          <add name="SQLConnect"
               connectionString="Data Source=SAHIL; Initial Catalog=Demo; Integrated Security=SSPI"
               providerName="System.Data.SqlClient" />  
       </connectionStrings>    
       <configSections>  
          <sectionnamesectionname="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework,
              Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
       </configSections>    
       :  
       :  
       :  
       :  
       :  
       :  
       :  
    </configuration>

When I run the application, I experienced a strange error that says: "Only one <configSections> element allowed. It must be the first child element of the root <configuration> element".

It took me some time to determine the cause of the error and how to fix it.
Error: "Only one <configSections> element allowed. It must be the first child element of the root <configuration> element".

If you read the error carefully, it states that only one <configSections> element is allowed inside the Web.config and it should be the first child element and placed at the top. The reason for the error is that I accidentally placed the <connectionStrings></connectionStrings> at the top over the <configSections></configSections> and by conventions this is a violation. So, to fix the error, I rearranged the elements and the error was fixed.

<?xml version="1.0" encoding="utf-8"?>   
<configuration>  
   <configSections>  
      <sectionnamesectionname="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework,
       Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
   </configSections> 
   <connectionStrings>  
      <add name="SQLConnect"
           connectionString="Data Source=SAHIL; Initial Catalog=Demo; Integrated Security=SSPI"
           providerName="System.Data.SqlClient" />
   </connectionStrings>   
   :  
   :  
   :  
   :  
   :  
   :  
   :  
</configuration>

Conclusion

Your feedback and constructive criticism is always appreciated, keep it coming. Until then try to put a ding in the Universe. 



ASP.NET MVC - ASPHostPortal.com :: 7 Tips for Developing a Secure ASP.NET Web Application

clock March 7, 2016 20:07 by author Armend

As the usage of the internet and the number of web applications over the internet have gone exponentially high there are bad people who continuously work around the clock to hack them. It may be for personal gain or just as an amateur act. Despite the intention of the bad guy the damage caused to the organization hosting the site or its users should be taken into account. As a professional web application developer it is a must to be aware of the best practices to follow in order to make the application more secure. In this article I will be listing and explaining my top 7 tips for developing a secure asp.net application.

Don’t Let Your Users be Victims of Click Jacking

Have you ever thought about someone framing your website onto theirs, making your users to be the victims of click jacking? Yes, the attackers can load your website onto their site in an iframe. They can then skillfully place their transparent controls over your website and fetch the PII information, user credentials, make them perform an unwanted task like exposing their financial information, etc.
In order to prevent that you will have to use a frame busting technique. The following script will not allow your website to be iframed. This can be placed in your master pages.

<script type="text/javascript" language="javascript">
        //Check if the top location is same as the current location
        if (top.location.hostname != self.location.hostname) {
            //If not then set the top to you current
            top.location.href = self.location.href;
        }
    </script>

In addition to the above script don’t forget to add the following header, which informs the browser to DENY framing of this website. This is supported in all major browsers except IE versions less than 8.
The header should be added in the global.asax application start event.  

protected void Application_Start(object sender, EventArgs e)
    {
                HttpContext.Current.Response.AddHeader("x-frame-options", "DENY");
    }    

White List the Request URL

Though we have many techniques to perform the security preventions inside the application it is most important to prevent the bad data from being entered into your website at the first place. Most attacks happen through the query string values passed through the URL. It is a best security practice to define a common place like an HttpModule to white list the URL, i.e. sanitize the entire URL with a set of white listed characters and drop all the bad ones. It means you will not encourage any other characters apart from a white listed set defined in your application.
It is important for you to know that black listing is not a foolproof mechanism and it can be broken by the hackers easily.

Practice of Encoding the Data

While processing and sending, the data in the response that is fetched from outside the trust boundary should always be encoded. The type of encoding may differ based on the usage of the non-trusted data. For example perform an HtmlEncode for the data that is sent to the client page.

Label1.Text = Server.HtmlEncode(Request.QueryString["BadValue"]);

Encoding the data will make the XSS scripts inactive and prevent them from being executed. Microsoft has provided the AntiXss library, which provides more sophisticated encoding methods including the JavascriptEncode.
Using Cookies
As a web developer you should take utmost care while using cookies, which may open a back door for the hackers to get into your applications. Following are the best practices while using a cookie to store information.

1. Is your website is hosted under SSL? Then be sure to mark your cookies as secure. This will make them available only in the SSL transmissions.

             HttpCookie cookie = new HttpCookie("MySecureCookie");
        cookie.Value = "This is a PII information";
        cookie.Secure = true;

2. If your website is not SSL enabled then always encrypt the values using a strong encryption mechanism like AES 256 and then store them in the cookies.

Secure the Service Calls (WCF / Web Service)

Are you exposing WCF services through basicHttpBinding? Then think again because the messages transmitted over will be plain text and any intruder will be able to trap the requests and even simulate them easily. Use wsHttpBinding, which will transport the messages in an encrypted format, which makes the life of the intruder hard.
Though you make lots of protections for your WCF or web services it is a best practice to host the services under an SSL layer.

Never Deploy the Application with debug=”true”

It is strongly recommended not to deploy your applications in the production environment with compilation debug=”true” in your web.config. This will result in a big nightmare for performance and security of the application.
This may leak too much information for the attackers, for example the stack trace in the event of an unhandled exception and the debug trace information. Such exposure of the internals will be good bucks for the attackers.

<system.web>
        <compilation debug="false" targetFramework="4.0" />
    </system.web>

Thinking About Turning Off ViewStateMAC?

Turning off ViewStateMAC will create a security loophole in your asp.net application if you are using Viewstate on your web pages. The intruders will easily be able to intercept, read the 64 bit encoded values and modify them to do some bad things to your website. Having it turned on ensures that the viewstate values are not only encoded but also a cryptographic hash is performed using a secret key.

<pages enableViewStateMac="true"></pages>

I hope this article is useful for the developers who thrive at making their asp.net application an absolutely impossible place for the hackers to deal with.
Happy reading!



ASP.NET MVC - ASPHostPortal.com :: Simple Tips for ASP.NET MVC Model Binding

clock March 1, 2016 18:25 by author Armend

Tips for ASP.NET MVC Model Binding

Model binding in the ASP.NET MVC framework is simple. Your action methods need data, and the incoming HTTP request carries the data you need. The catch is that the data is embedded into POST-ed form values, and possibly the URL itself. Enter the DefaultModelBinder, which can magically convert form values and route data into objects. Model binders allow your controller code to remain cleanly separated from the dirtiness of interrogating the request and its associated environment.    
Here are some tips on how to take advantage of model binding in your MVC projects.

 

Tip #1: Prefer Binding Over Request.Form

If you are writing your actions like this ..

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create()

{
    Recipe recipe = new Recipe();
    recipe.Name = Request.Form["Name"];  
    // ...  
    return View();
}

Then you are doing it all wrong. The model binder can save you from using the Request and HttpContext properties – those properties make the action harder to read and harder to test. One step up would be to use a FormCollection parameter instead:
public ActionResult Create(FormCollection values)

{
    Recipe recipe = new Recipe();
    recipe.Name = values["Name"];               
    // ...        
    return View();
}

With the FormCollection you don’t have to dig into the Request object, and sometimes you need this low level of control. But, if all of your data is in Request.Form, route data, or the URL query string, then you can let model binding work its magic:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Recipe newRecipe)
{           
    // ...  
    return View();
}

In this example, the model binder will create your newRecipe object and populate it with data it finds in the request (by matching up data with the recipe’s property names). It’s pure auto-magic. There are many ways to customize the binding process with “white lists”, “black lists”, prefixes, and marker interfaces. For more control over when the binding takes place you can use the  UpdateModel and TryUpdateModel methods. Just beware of unintentional binding – see Justin Etheredge’s Think Before You Bind.

Tip #2: Custom model binders

Model binding is also one of the extensibility points in the MVC framework. If you can’t use the default binding behavior you can provide your own model binders, and mix and match binders. To implement a custom model binder you need to implement the IModelBinder interface. There is only method involved - how hard can it be?
public interface IModelBinder

{
    object BindModel(ControllerContext controllerContext,
                     ModelBindingContext bindingContext);
}

Once you get neck deep into model binding, however, you’ll discover that the simple IModelBinder interface doesn’t fully describe all the implicit contracts and side-effects inside the framework.  If you take a step back and look at the bigger picture you’ll see that model binding is but one move in a carefully orchestrated dance between the model binder, the ModelState, and the HtmlHelpers. You can pick up on some of these implicit behaviors by reading the unit tests for the default model binder.

If the default model binder has problems putting data into your object, it will place the error messages and the erroneous data value into ModelState. You can check ModelState.IsValid to see if binding problems are present, and use ModelState.AddModelError to inject your own error messages. See this very simple tutorial for more information on how ModelState and HtmlHelpers can work together to present validation errors to the user. 
If you scroll down the comments to post you’ll see code. If a conversion fails, the code will use ModelState.AddModelError to propagate the error. Both the controller action and the view can look in ModelState to see if there was a binding problem. The controller would need to check ModelState for errors before saving stuff into the database, while the view can check ModelState for errors to give the user validation feedback. One important note is that the HtmlHelpers you use in a view will require ModelState to hold both a value (via ModelState.SetModelValue) and the error (via AddModelError) or you’ll have runtime errors (null reference exceptions). The following code can demonstrate the problem:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection Form)
{
    // this is the wrong approach ...
    if (Form["Name"].Trim().Length == 0)
        ModelState.AddModelError("Name", "Name is required");
    return View();
}

The above code creates a model error without ever setting a model value. It has other problems, too, but it will create exceptions if you render the following view.

<%= Html.TextBox("Name", Model.Name) %>

Even though you’ve specified Model.Name as the value for the textbox, the textbox helper will see the model error and attempt to display the “attempted value” that the user tried to put in the model. If you didn’t set the model value in model state you’ll see a null reference exception.

Tip #3: Custom Model Binding via Inheritance

If you’ve decided to implement a custom model binder, you might be able to cut down on the amount of work required by inheriting from DefaultModelBinder and adding some custom logic. In fact, this should be your default plan until you are certain you can’t subclass the default binder to achieve the functionality you need. For example, suppose you just want to have some control over the creation of your model object. The DefaultModelBinder will create object’s using Activator.CreateInstance and the model’s default constructor. If you don’t have a default constructor for your model, you can subclass the DefaultModelBinder and override the CreateModel method.
Jimmy Bogard has an example of sub classing the DefaultModelBinder in his post titled “A Better Model Binder”.

Tip #4: Using Data Annotations for Validation

Brad Wilson explains everything beautifully in this post: DataAnnotations and ASP.NET MVC.
I encourage you to go read Brad’s post, but if you are in a hurry, here is a summary:

.NET 3.5 SP1 shipped a System.ComponentModel.DataAnnotations assembly that looks to play a central role as we move forward with the .NET framework. By using data annotations and the DataAnnotationsModelBinder, you can take care of most of your server-side validation by simply decorating your model with attributes.

public class Recipe
{
    [Required(ErrorMessage="We need a name for this dish.")]
    [RegularExpression("^Bacon")]
    public string Name { get; set; }

    // ...
}

The DataAnnotationsModelBinder is also a great sample to read and understand how to effectively subclass the default model binder.

Tip #5 : Recognize Binding and Validation As Two Phases

Binding is about taking data from the environment and shoving it into the model, while validation is checking the model to make sure it meets our expectations. These are different different operations, but model binding tends to blur the distinction. If you want to perform validation and binding together in a model binder, you can – it’s exactly what the DataAnnotationsModelBinder will do. You can also find samples like Automatic Model Validation with ASP.NET MVC, xVal, Castle, and a Custom Binder (John McDowall), and Enterprise Library Validation Application Block with MVC Binders (Steve Michelotti).  However, one thing that is often overlooked is how the DefaultModelBinder itself separates the binding and validation phases. If all you need is simple property validation, then all you need to do is override the OnPropertyValidating method of the DefaultModelBinder.

Tip #6: Binders Are About The Environment

Earlier I said that “model binders allow your controller code to remain cleanly separated from the dirtiness of interrogating the request and its associated environment”. Generally, when we think of binder we think of moving data from the routing data and posted form values into the model. However, there is no restriction of where you find data for your model. The context of a web request is rich with information about the client. A good example is another Scott Hanselman post on automatically binding the user’s identity into a model see: IPrincipal (User) ModelBinder in ASP.NET MVC for easier testing.

In Conclusion

Model binding is beautiful magic, so take advantage of the built-in magic when you can. I think the topic of model binding could use it’s own dedicated web site. It would be a very boring web site with lots of boring code, but model binding has many subtleties. For instance, we never even got to the topic of culture in this post.
Do you have any model binding tips?



ASP.NET MVC 6 Hosting - ASPHostPortal :: Creating Custom Controller Factory ASP.NET MVC

clock February 20, 2016 00:01 by author Jervis

I was reading about “Control application behavior by using MVC extensibility points” which is one of the objectives for the 70-486 Microsoft certification, and it was not clear to me, the explanation provided. So I decided to write about it to make clear for me, and I hope this help you as well.

An ASP.NET MVC application contains the following class:

public class HomeController: Controller
{
   public HomeController(Ilogger logger)//notice the parameter in the constructor
   { 

   }
}

This throw an error with the DefaultControllerFactory see image below.

The application won’t be able to load the Home controller because it have a parameter. You need to ensure that Home Controller can be instantiated by the MVC framework. In order to accomplish this we are going to use dependency injection.

The solution is to create a custom controller factory.

It calls the default constructor of that class. To have the MVC framework create controller class instances for constructors that have parameters, you must use a custom controller factory. To accomplish this, you create a class that implements IControllerFactory and implement its methods. You then call the SetControllerFactory method of the ControllerBuilder class to an instance of your custom controller factory class.

Create the CustomControllerFactory that inherit from IControllerFactory:

public class CustomControllerFactory : IControllerFactory
   { 

       public CustomControllerFactory()
       {
       }  


       public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
       {
            ILogger logger = new DefaultLogger();
       var controller = new HomeController(logger);
       return controller;
       } 

       public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(System.Web.Routing.RequestContext requestContext, string controllerName)
       {
            return SessionStateBehavior.Default;
       } 

       public void ReleaseController(IController controller)
       {
           var disposable = controller as IDisposable;
           if (disposable != null)
           {
               disposable.Dispose();
           } 

       }
   }

You can implement the CreateController() method with a more generic way, using reflection.

public class CustomControllerFactory : IControllerFactory
{
    private readonly string _controllerNamespace;
    public CustomControllerFactory(string controllerNamespace)
    {
        _controllerNamespace = controllerNamespace;
    }
    public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        ILogger logger = new DefaultLogger();
        Type controllerType = Type.GetType(string.Concat(_controllerNamespace, ".", controllerName, "Controller"));
        IController controller = Activator.CreateInstance(controllerType, new[] { logger }) as Controller;
        return controller;
    }
}

Set your controller factory in Application_Start by using SetControllerFactory method:

protected void Application_Start()
       {
           AreaRegistration.RegisterAllAreas();
           GlobalConfiguration.Configure(WebApiConfig.Register);
           FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
           RouteConfig.RegisterRoutes(RouteTable.Routes);
           BundleConfig.RegisterBundles(BundleTable.Bundles); 

           ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));
       }

This could be one of the objective of the Microsoft certification exam 70-486, more specific for “Develop the user experience”, sub-objective “Control application behavior by using MVC extensibility points”.

Hope this helped you to understand how to do dependency injection in controllers with MVC.

 

 



ASP.NET MVC Hosting - ASPHostPortal :: The Difference Between Controller and View in ASP.NET MVC

clock November 12, 2015 20:28 by author Jervis

One of the basic rules of MVC is that views should be only – exactly – views, that is to say: objects that present to the user something that is already “worked and calculated”.

They should perform little, if not none at all, calculation. All the significant code should be in the controllers. This allows better testability and maintainability.

Is this, in Microsoft’s interpretation of MVC, also justified by performance?

We tested this with a very simple code that does this:

– creates 200000 “cat” objects and adds them to a List

– creates 200000 “owner” objects and adds them to a List

– creates 200000 “catowner” objects (the MTM relation among cats and owners) and adds them to a List

– navigates through each cat, finds his/her owner, removes the owner from the list of owners (we don’t know if cats really wanted this, but their freedom on code fits our purposes).

We’ve run this code in a controller and in a razor view.

The result seem to suggest that the code in views runs just as fast as in controllers even if don’t pre-compile views (the compilation time in our test is negligible).

The average result for the code with the logic in the controller is 18.261 seconds.

The average result for the code with the logic in the view is 18.621 seconds.

The performance seems therefore very similar.

Here is how we got to this result.

Case 1: Calculations are in the CONTROLLER

Models:

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

namespace WebPageTest.Models
{
public class Owner
{
public string Name { get; set; }
public DateTime DOB { get; set; }
public virtual CatOwner CatOwner { get; set; }
}
public class Cat
{
public string Name { get; set; }
public DateTime DOB { get; set; }
public virtual CatOwner CatOwner { get; set; }
}
public class CatOwner
{
public virtual Cat Cat { get; set; }
public virtual Owner Owner { get; set; }
}
}

Controller:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebPageTest.Models;

namespace WebPageTest.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
Stopwatch howLongWillItTake = new Stopwatch();
howLongWillItTake.Start();
List<Owner> allOwners = new List<Owner>();
List<Cat> allCats = new List<Cat>();
List<CatOwner> allCatOwners = new List<CatOwner>();
// create lists with 200000 cats, 200000 owners, 200000 relations
for (int i = 0; i < 200000; i++)
{
//Cat
Cat CatX = new Cat();
CatX.Name = “Cat ” + i.ToString();
CatX.DOB = DateTime.Now.AddDays(i / 10);
//Owner
Owner OwnerX = new Owner();
OwnerX.Name = “Owner ” + i.ToString();
OwnerX.DOB = DateTime.Now.AddDays(-i / 10);
//Relationship “table”
CatOwner CatOwnerXX = new CatOwner();
CatOwnerXX.Cat = CatX;
// Relations
CatOwnerXX.Owner = OwnerX;
CatX.CatOwner = CatOwnerXX;
OwnerX.CatOwner = CatOwnerXX;
//add to list
allCats.Add(CatX);
allOwners.Add(OwnerX);
allCatOwners.Add(CatOwnerXX);
}
// now I remove all the items
foreach (Cat CatToDelete in allCats)
{
Owner OwnerToRemove = CatToDelete.CatOwner.Owner;
allOwners.Remove(OwnerToRemove);
}
// now all cats are free
int numberOfCats = allCats.Count();
int numberOfOwners = allOwners.Count();
howLongWillItTake.Stop();
long elapsedTime = howLongWillItTake.ElapsedMilliseconds;
// give info to the view
ViewBag.numberOfCats = numberOfCats;
ViewBag.numberOfOwners = numberOfOwners;
ViewBag.elapsedTime = elapsedTime;
return View();
}
}
}

View:

<div class=”row”>
<div class=”col-md-12″>
<hr />
<b>Results</b>
<br/>
Cats: @ViewBag.numberOfCats
<br/>
Owners: @ViewBag.numberOfOwners
<br/>
ElapsedTime in milliseconds: @ViewBag.ElapsedTime
<hr />
</div>
</div>

Case 2: Calculations are in the VIEW (pre-compiled)

Models: same as above

Controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebPageTest.Controllers
{
public class HomeBisController : Controller
{
public ActionResult Index()
{
return View();
}
}
}

View:

@using System;
@using System.Collections.Generic;
@using System.Diagnostics;
@using System.Linq;
@using System.Web;
@using WebPageTest.Models;
@using System.Web.Mvc;
@{
Stopwatch howLongWillItTake = new Stopwatch();
howLongWillItTake.Start();
List<Owner> allOwners = new List<Owner>();
List<Cat> allCats = new List<Cat>();
List<CatOwner> allCatOwners = new List<CatOwner>();
//create lists with 200000 cats, 200000 owners, 200000 relations
for (int i = 0; i < 200000; i++)
{
//Cat
Cat CatX = new Cat();
CatX.Name = “Cat ” + i.ToString();
CatX.DOB = DateTime.Now.AddDays(i / 10);
//Owner
Owner OwnerX = new Owner();
OwnerX.Name = “Owner ” + i.ToString();
OwnerX.DOB = DateTime.Now.AddDays(-i / 10);
//Relationship “table”
CatOwner CatOwnerXX = new CatOwner();
CatOwnerXX.Cat = CatX;
// Relations
CatOwnerXX.Owner = OwnerX;
CatX.CatOwner = CatOwnerXX;
OwnerX.CatOwner = CatOwnerXX;
//add to list
allCats.Add(CatX);
allOwners.Add(OwnerX);
allCatOwners.Add(CatOwnerXX);
}
// now I remove all the items
foreach (Cat CatToDelete in allCats)
{
Owner OwnerToRemove = CatToDelete.CatOwner.Owner;
allOwners.Remove(OwnerToRemove);
}
// now all cats are free
int numberOfCats = allCats.Count();
int numberOfOwners = allOwners.Count();
howLongWillItTake.Stop();
long elapsedTime = howLongWillItTake.ElapsedMilliseconds;
// give info to the view

}
<div class=”row”>
<div class=”col-md-12″>
<hr />
<b>Results</b>
<br />
Cats: @numberOfCats
<br />
Owners: @numberOfOwners
<br />
ElapsedTime in milliseconds: @elapsedTime
<hr />
</div>
</div>

 



ASP.NET MVC 4 Hosting - ASPHostPortal.com :: A Best Practice for Authenticating Users in ASP.NET MVC 4

clock December 20, 2013 06:16 by author Robert

If your site has even one or two actions where access is restricted to particular users, the smart thing to do is to restrict access to all the actions on your site and then selectively permit access to those actions that all users are allowed to request. That way, an error of omission (forgetting to make a method available) simply prevents users from accessing some action.

Unfortunately, by default ASP.NET MVC works exactly the opposite way: all actions are accessible to all users unless you specifically restrict access by applying the Authorization action filter to the method. Under this scenario, an error of omission (forgetting to put an Authorize attribute on a method) allows all users access to the action. It's literally the worst thing that can happen in a secure environment: unauthenticated and unauthorized access to a resource that should have been secured.

Global Filters provided a solution to this by allowing you to apply the Authorize attribute to all of your action methods, locking non-authenticated users out of your actions by default. You can then selectively override that setting by applying the Authorize attribute to individual methods, specifying specific roles and users authorized to use that action. That works, unless you have some action methods that don't require authentication, methods intended to be accessible to the general public. In that scenario, you can't use Global Filters to secure all of your action methods -- until ASP.NET MVC 4.

Implementing the best practice is possible in ASP.NET MVC 4 with the new AllowAnonymous action filter. The first step is to use the Global Filters in the FilterConfig class in the App_Start folder to apply the Authorize attribute to every action method:

public class FilterConfig
{
  public static void RegisterGlobalFilters(GlobalFilterCollection filters)
  {
    filters.Add(new AuthorizeAttribute);
  }
}


The next step is to selectively allow access to actions that don't require authentication by decorating them with the AllowAnonymous attribute:

[AllowAnonymous]
Public ActionResult Get()
{

 



ASP.NET MVC 3 Hosting - ASPHostPortal :: Set up custom error pages to handle errors in “non-AJAX” requests and jQuery AJAX requests

clock May 4, 2012 08:16 by author Jervis

In this blog post I will show how to set up custom error pages in ASP.NET MVC 3 applications to create user-friendly error messages instead of the (yellow) IIS default error pages for both “normal” (non-AJAX) requests and jQuery AJAX requests.

In this showcase we will implement custom error pages to handle the HTTP error codes 404 (“Not Found”) and 500 (“Internal server error”) which I think are the most common errors that could occur in web applications. In a first step we will set up the custom error pages to handle errors occurring in “normal” non-AJAX requests and in a second step we add a little JavaScript jQuery code that handles jQuery AJAX errors.

We start with a new (empty) ASP.NET MVC 3 project and activate custom errors in the Web.config by adding the following lines under <system.web>:

<customErrors
mode="On" defaultRedirect="/Error">
  <error redirect="/Error/NotFound" statusCode="404"/>
  <error redirect="/Error/InternalServerError" statusCode="500"/>
</customErrors>


Note: You can set
mode=Off” to disable custom errors which could be helpful while developing or debugging. Setting mode=RemoteOnly” activates custom errors only for remote clients, i.e. disables custom errors when accessing via http://localhost/[...]. In this example setting mode=”On” is fine since we want to test our custom errors. You can find more information about the <customErrors> element here.

In a next step we
remove the following line in Global.asax.cs file:

filters.Add(new HandleErrorAttribute());


and add a new
ErrorController (Controllers/ErrorController.cs):

public class ErrorController : Controller
{
  public ActionResult Index()
  {
    return InternalServerError();
  }

  public ActionResult NotFound()
  {
    Response.TrySkipIisCustomErrors = true;
    Response.StatusCode = (int)HttpStatusCode.NotFound;
    return View("NotFound");
  }

  public ActionResult InternalServerError()
  {
    Response.TrySkipIisCustomErrors = true;
    Response.StatusCode = (int)HttpStatusCode.InternalServerError;
    return View("InternalServerError");
  }
}

In a last step we add the ErrorController‘s views (Views/Error/NotFound.cshtml and Views/Error/InternalServerError.cshtml) that defines the (error) pages the end user will see in case of an error. The views include a partial view defined in Views/Shared/Error/NotFoundInfo.cshtml respectively Views/Shared/Error/InternalServerErrorInfo.cshtml that contains the concrete error messages. As we will see below using these partial views enables us to reuse the same error messages to handle AJAX errors.

Views/Error/NotFound.cshtml:
@{
  ViewBag.Title = "Not found";
}
@{
  Html.RenderPartial("Error/NotFoundInfo");
}

Views/Shared/Error/NotFoundInfo.cshtml:

The URL you have requested was not found.

Views/Error/InternalServerError.cshtml:

@{

  ViewBag.Title = "Internal server error";
}
@{
  Html.RenderPartial("Error/InternalServerErrorInfo");
}

Views/Shared/Error/InternalServerErrorInfo.cshtml:

An internal Server error occured.

To handle errors occurring in (jQuery) AJAX calls we will use jQuery UI to show a dialog containing the error messages. In order to include jQuery UI we need to add two lines to Views/Shared/_Layout.cshtml:

<link href="@Url.Content("~/Content/themes/base/jquery.ui.all.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"></script>

Moreover we add the following jQuery JavaScript code (defining the global AJAX error handling) and the Razor snippet (defining the dialog containers) to Views/Shared/_Layout.cshtml:

<script type="text/javascript">
  $(function () {
    // Initialize dialogs ...
    var dialogOptions = {
      autoOpen: false,
      draggable: false,
      modal: true,
      resizable: false,
      title: "Error",
      closeOnEscape: false,
      open: function () { $(".ui-dialog-titlebar-close").hide(); }, // Hide close button
      buttons: [{
        text: "Close",
        click: function () { $(this).dialog("close"); }
      }]
    };
    $("#InternalServerErrorDialog").dialog(dialogOptions);
    $("#NotFoundInfoDialog").dialog(dialogOptions);

    // Set up AJAX error handling ...
    $(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
      if (jqXHR.status == 404) {
        $("#NotFoundInfoDialog").dialog("open");
      } else if (jqXHR.status == 500) {
        $("#InternalServerErrorDialog").dialog("open");
      } else {
        alert("Something unexpected happend :( ...");
      }
    });
  });
</script>

<div id="NotFoundInfoDialog">
  @{ Html.RenderPartial("Error/NotFoundInfo"); }
</div>
<div id="InternalServerErrorDialog">
  @{ Html.RenderPartial("Error/InternalServerErrorInfo"); }
</div>

As you can see in the Razor snippet above we reuse the error texts defined in the partial views saved in Views/Shared/Error/.

To test our custom errors we define the HomeController (Controllers/HomeController.cs) as follows:

  public class HomeController : Controller
  {
  public ActionResult Index()
  {
    return View();
  }
  public ActionResult Error500()
  {
    throw new Exception();
  }
}


and the corresponding view
Views/Home/Index.cshtml:

@{

  ViewBag.Title = "ViewPage1";
}


<
script type="text/javascript">
  $function () {
    $("a.ajax").click(function (event) {
      event.preventDefault();
      $.ajax({
      url: $(this).attr('href'),
    });
  });
});

</
script>

<
ul>
  <li>@Html.ActionLink("Error 404 (Not Found)", "Error404")</li>
  <li>@Html.ActionLink("Error 404 (Not Found) [AJAX]", "Error404", new { }, new { Class = "ajax" })</li>
  <li>@Html.ActionLink("Error 500 (Internal Server Error)", "Error500")</li>
  <li>@Html.ActionLink("Error 500 (Internal Server Error) [AJAX]", "Error500", new { }, new { Class = "ajax" })</li>
</
ul>

To test the custom errors you can launch the project and click one of the four links defined in the view above. The “AJAX links” should open a dialog containing the error message and the “non-AJAX” links should redirect to a new page showing the same error message.


Summarized this blog post shows how to set up custom errors that handle errors occurring in both AJAX requests and “non-AJAX” requests. Depending on the project, one could customize the example code shown above to handle other HTTP errors as well or to show more customized error messages or dialogs.


Reasons why you must trust ASPHostPortal.com

Every provider will tell you how they treat their support, uptime, expertise, guarantees, etc., are. Take a close look. What they’re really offering you is nothing close to what
ASPHostPortal does. You will be treated with respect and provided the courtesy and service you would expect from a world-class web hosting business.

You’ll have highly trained, skilled professional technical support people ready, willing, and wanting to help you 24 hours a day. Your web hosting account servers are monitored from three monitoring points, with two alert points, every minute, 24 hours a day, 7 days a week, 365 days a year. The followings are the list of other added- benefits you can find when hosting with us:

- DELL Hardware
Dell hardware is engineered to keep critical enterprise applications running around the clock with clustered solutions fully tested and certified by Dell and other leading operating system and application providers.
- Recovery Systems
Recovery becomes easy and seamless with our fully managed backup services. We monitor your server to ensure your data is properly backed up and recoverable so when the time comes, you can easily repair or recover your data.

- Control Panel
We provide one of the most comprehensive customer control panels available. Providing maximum control and ease of use, our Control Panel serves as the central management point for your ASPHostPortal account. You’ll use a flexible, powerful hosting control panel that will give you direct control over your web hosting account. Our control panel and systems configuration is fully automated and this means your settings are configured automatically and instantly.

- Excellent Expertise in Technology
The reason we can provide you with a great amount of power, flexibility, and simplicity at such a discounted price is due to incredible efficiencies within our business. We have not just been providing hosting for many clients for years, we have also been researching, developing, and innovating every aspect of our operations, systems, procedures, strategy, management, and teams. Our operations are based on a continual improvement program where we review thousands of systems, operational and management metrics in real-time, to fine-tune every aspect of our operation and activities. We continually train and retrain all people in our teams. We provide all people in our teams with the time, space, and inspiration to research, understand, and explore the Internet in search of greater knowledge. We do this while providing you with the best hosting services for the lowest possible price.

- Data Center

ASPHostPortal modular Tier-3 data center was specifically designed to be a world-class web hosting facility totally dedicated to uncompromised performance and security
- Monitoring Services
From the moment your server is connected to our network it is monitored for connectivity, disk, memory and CPU utilization – as well as hardware failures. Our engineers are alerted to potential issues before they become critical.

- Network
ASPHostPortal has architected its network like no other hosting company. Every facet of our network infrastructure scales to gigabit speeds with no single point of failure.

- Security
Network security and the security of your server are ASPHostPortal’s top priorities. Our security team is constantly monitoring the entire network for unusual or suspicious behavior so that when it is detected we can address the issue before our network or your server is affected.

- Support Services
Engineers staff our data center 24 hours a day, 7 days a week, 365 days a year to manage the network infrastructure and oversee top-of-the-line servers that host our clients’ critical sites and services.

 



ASP.NET MVC 3 Hosting - ASPHostPortal :: User Activity logging in ASP.NET MVC app using Action Filter and log4net

clock April 6, 2012 07:59 by author Jervis

In this post, I will demonstrate how to use an action filter to log user tracking information in an ASP.NET MVC app. The below action filter will take logged user name, controller name, action name, timestamp information and the value of route data id. These user tracking information will be logged using log4net logging framework.

public class UserTrackerAttribute : ActionFilterAttribute, IActionFilter

{         


    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var actionDescriptor= filterContext.ActionDescriptor;
        string controllerName = actionDescriptor.ControllerDescriptor.ControllerName;
        string actionName = actionDescriptor.ActionName;
        string userName = filterContext.HttpContext.User.Identity.Name.ToString();
        DateTime timeStamp = filterContext.HttpContext.Timestamp;
        string routeId=string.Empty;
        if (filterContext.RouteData.Values["id"] != null)
        {
            routeId = filterContext.RouteData.Values["id"].ToString();
        }
        StringBuilder message = new StringBuilder();
        message.Append("UserName=");
        message.Append(userName + "|");
        message.Append("Controller=");
        message.Append(controllerName+"|");
        message.Append("Action=");
        message.Append(actionName + "|");
        message.Append("TimeStamp=");
        message.Append(timeStamp.ToString() + "|");
        if (!string.IsNullOrEmpty(routeId))
        {
            message.Append("RouteId=");
            message.Append(routeId);
        }
        var log=ServiceLocator.Current.GetInstance<ILoggingService>();
        log.Log(message.ToString());
        base.OnActionExecuted(filterContext);
    }
}

The LoggingService class is given below


public class LoggingService : ILoggingService

    {
        private static readonly ILog log = LogManager.GetLogger
            (MethodBase.GetCurrentMethod().DeclaringType);
        public void Log(string message)
        {
            log.Info(message);
        }
    }
    public interface ILoggingService
    {
        void Log(string message);
    }

The LoggingService class is using log4net framework for logging. You can add reference to log4net using
NuGet.

The following command on NuGet console will install log4net into your ASP.NET MVC app.

PM> install-package Log4Net

The below configuration information in web.config will configure log4net for using with Sql Server

Let me add a log4net section to the <configSections> of web.config

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>

The below is the log4net section in the web.config file

<log4net>
    <root>
      <level value="ALL"/>
      <appender-ref ref="ADONetAppender"/>
    </root>
    <appender name="ADONetAppender" type="log4net.Appender.AdoNetAppender">
      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <connectionString value="data source=.\SQLEXPRESS;Database=MyFinance;Trusted_Connection=true;" />
      <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message]) VALUES (@log_date, @thread, @log_level, @logger, @message)" />
      <parameter>
        <parameterName value="@log_date" />
        <dbType value="DateTime" />
        <layout type="log4net.Layout.PatternLayout" value="%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}" />
      </parameter>
      <parameter>
        <parameterName value="@thread" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout" value="%thread" />
      </parameter>
      <parameter>
        <parameterName value="@log_level" />
        <dbType value="String" />
        <size value="50" />
        <layout type="log4net.Layout.PatternLayout" value="%level" />
      </parameter>
      <parameter>
        <parameterName value="@logger" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout" value="%logger" />
      </parameter>
      <parameter>
        <parameterName value="@message" />
        <dbType value="String" />
        <size value="4000" />
        <layout type="log4net.Layout.PatternLayout" value="%message" />
      </parameter>
    </appender>
  </log4net>


Configure log4net

The below code in the Application_Start() of Global.asax.cs will configure the log4net

log4net.Config.XmlConfigurator.Configure();


The below Sql script is used for creating table in Sql Server for logging information

CREATE TABLE [dbo].[Log] (
[ID] [int] IDENTITY (1, 1) NOT NULL ,
[Date] [datetime] NOT NULL ,
[Thread] [varchar] (255) NOT NULL ,
[Level] [varchar] (20) NOT NULL ,
[Logger] [varchar] (255) NOT NULL ,
[Message] [varchar] (4000) NOT NULL
) ON [PRIMARY]

 



ASP.NET MVC 3 Hosting - ASPHostPortal :: ASP.NET MVC 3 Routing

clock March 15, 2012 07:52 by author Jervis

Routing in an ASP.NET module is responsible for mapping incoming browser requests to a particular MVC controller action.

When Requests arrive to an ASP.NET MVC-based web application it actually first passes through the UrlRoutingModule object, which is an HTTP module.


This module parses the request; i.e. the request from the URL and performs route selection. The UrlRoutingModule object selects the first route object that matches the current request.


If no routes match, the UrlRoutingModule object does nothing and lets the request fall back to the regular ASP.NET or IIS request processing.


Now From the selected Route object, the UrlRoutingModule object contains the IRouteHandler object that is associated with the Route object. This is an instance of MvcRouteHandler. The IRouteHandler instance creates an IHttpHandler object that passes it the IHttpContext object. By default, the IHttpHandler instance for MVC is the MvcHandler object. The MvcHandler object then selects the controller that will ultimately handle the request.


See when an ASP.NET MVC web application runs in IIS 7.0, no file name extension is required for MVC projects. So you cannot find the .aspx,.ascx,.asmx extension.


Now when you create a new ASP.NET MVC application, it will automatically configure to use ASP.NET Routing. ASP.NET Routing is set up in two places:


1. Webconfig File

2. Global.asax file

Now interestingly when you create a MVC2 application a route table is automatically created in the application's Global.asax file.


As we all know the Global.asax contains event handlers for ASP.NET application lifecycle events. The route table is created during the Application Start event. So when you open the Global.asax file you will see the following code:


using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using System.Web.Routing;

namespace MvcApplication1

{

// Note: For instructions on enabling IIS6 or IIS7 classic mode,

// visit http://go.microsoft.com/?LinkId=9394801

public class MvcApplication : System.Web.HttpApplication

{

public static void RegisterRoutes(RouteCollection routes)

{

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(

"Default", // Route name

"{controller}/{action}/{id}", // URL with parameters

new { controller = "Home", action = "Index", id = "" } // Parameter defaults

);

}

protected void Application_Start()

{

RegisterRoutes(RouteTable.Routes);

}

}

}


See here the routing is occuring in the "RegisterRoutes" method.


See in the routes.MapRoute method we are passing 3 parameters.


1. Controller(Name of the controller)

2. Action (The method inside the controller)
3. id (Parameter)

See in the above url before home it is domain. The home is control. The action method is the index with parameter id. Now in the home controller the code will be:


using System.Web.Mvc;

namespace MvcApplication1.Controllers

{

public class HomeController : Controller

{

public ActionResult Index(int id)

{

return View();

}

}

}


Conclusion:
So in this article we have seen what the functionality of routing in ASP.Net MVC 3 is.

Reasons why you must trust ASPHostPortal.com

Every provider will tell you how they treat their support, uptime, expertise, guarantees, etc., are. Take a close look. What they’re really offering you is nothing close to what
ASPHostPortal does. You will be treated with respect and provided the courtesy and service you would expect from a world-class web hosting business.

You’ll have highly trained, skilled professional technical support people ready, willing, and wanting to help you 24 hours a day. Your web hosting account servers are monitored from three monitoring points, with two alert points, every minute, 24 hours a day, 7 days a week, 365 days a year. The followings are the list of other added- benefits you can find when hosting with us:

- DELL Hardware
Dell hardware is engineered to keep critical enterprise applications running around the clock with clustered solutions fully tested and certified by Dell and other leading operating system and application providers.
- Recovery Systems
Recovery becomes easy and seamless with our fully managed backup services. We monitor your server to ensure your data is properly backed up and recoverable so when the time comes, you can easily repair or recover your data.

- Control Panel
We provide one of the most comprehensive customer control panels available. Providing maximum control and ease of use, our Control Panel serves as the central management point for your ASPHostPortal account. You’ll use a flexible, powerful hosting control panel that will give you direct control over your web hosting account. Our control panel and systems configuration is fully automated and this means your settings are configured automatically and instantly.

- Excellent Expertise in Technology
The reason we can provide you with a great amount of power, flexibility, and simplicity at such a discounted price is due to incredible efficiencies within our business. We have not just been providing hosting for many clients for years, we have also been researching, developing, and innovating every aspect of our operations, systems, procedures, strategy, management, and teams. Our operations are based on a continual improvement program where we review thousands of systems, operational and management metrics in real-time, to fine-tune every aspect of our operation and activities. We continually train and retrain all people in our teams. We provide all people in our teams with the time, space, and inspiration to research, understand, and explore the Internet in search of greater knowledge. We do this while providing you with the best hosting services for the lowest possible price.

- Data Center

ASPHostPortal modular Tier-3 data center was specifically designed to be a world-class web hosting facility totally dedicated to uncompromised performance and security
- Monitoring Services
From the moment your server is connected to our network it is monitored for connectivity, disk, memory and CPU utilization – as well as hardware failures. Our engineers are alerted to potential issues before they become critical.

- Network
ASPHostPortal has architected its network like no other hosting company. Every facet of our network infrastructure scales to gigabit speeds with no single point of failure.

- Security
Network security and the security of your server are ASPHostPortal’s top priorities. Our security team is constantly monitoring the entire network for unusual or suspicious behavior so that when it is detected we can address the issue before our network or your server is affected.

- Support Services
Engineers staff our data center 24 hours a day, 7 days a week, 365 days a year to manage the network infrastructure and oversee top-of-the-line servers that host our clients’ critical sites and services.



ASP.NET MVC Hosting - ASPHostPortal :: Create ASP.NET MVC Localization with Language Detection

clock January 6, 2011 05:09 by author Jervis

In this tutorial I will show a simple way to create localization (globalization) for web application using APS.NET MVC framework. It should work fine with MVC 1 and 2 and I’m currently using .NET 3.5 SP1, but .NET 4.0 will work as well. All code is in C# and for language translations I use XML files.

Language files with XML


For translations of different languages I use simple xml files. I store them in App_Data/messages/<locale>.xml, for example en-US.xml or de-DE.xml. Here is the xml structure:

<items>
  <item key="home">Home</item>
  <item key="products">Products</item>
  <item key="services">Services</item>
</items>

You should have identical language files for all desired languages. All translation items should be the same (with equal “key” attributes).

Create Translator class

Main translation work will be done by Translator singleton class. Create “Infrastructure” folder in your MVC project and put class Translator there.
First, let’s make class singleton:


private static Translator instance = null;
public static Translator Instance
{
    get
    {
        if (instance == null)
        {
            instance = new Translator();
        }
        return instance;
    }
}
private Translator() { }

Add the following fields and properties to the class:

private static string[] cultures = { "en-US", "bg-BG" };
private string locale = string.Empty;

public string Locale
{
    get
    {
        if (string.IsNullOrEmpty(locale))
        {
            throw new Exception("Locale not set");
        }
        else
        {
            return locale;
        }
    }
    set
    {
        if (Cultures.Contains(value))
        {
            locale = value;
            load();
        }
        else
        {
            throw new Exception("Invalid locale");
        }
    }
}

public static string[] Cultures
{
    get
    {
        return cultures;
    }
}

Field "cultures" lists available cultures. "Locale" keeps current culture. And in "set" part of Locale property you can see invocation of load() method. I will talk about it later.
To keep localization data I will create simple dictionary and then use keys from XML for dictionary keys and XML item values as dictionary values. Simple Translate method will do translation job. I have indexer method for easy access.


private Dictionary data = null;

public string Translate(string key)
{
    if (data != null && data.ContainsKey(key))
    {
        return data[key];
    }
    else
    {
        return ":" + key + ":";
    }
}

public string this[string key]
{
    get
    {
        return Translate(key);
    }
}

If some key cannot be found and translated, I return the key with ":" around it, so you can easy find untranslated items.
Finally, for loading XML I use LINQ to XML. I have static caching dictionary, so I don't need reading XML on every request.


private static Dictionary<string, Dictionary<string, string>> cache =
  new Dictionary<string, Dictionary<string, string>>();

private void load()
{
    if (cache.ContainsKey(locale) == false) // CACHE MISS !
    {
        var doc = XDocument.Load(
            HttpContext.Current.Server.MapPath(
               "~/App_Data/messages/" + locale + ".xml"))

        cache[locale] = (from item in doc.Descendants("item")
                         where item.Attribute("key") != null
                         select new
                         {
                             Key = item.Attribute("key").Value,
                             Data = item.Value,
                         }).ToDictionary(i => i.Key, i => i.Data);
    }

    data = cache[locale];
}

public static void ClearCache()
{
    cache = new Dictionary<string, Dictionary<string, string>>();
}

You can use translator in your controller like this:
Translator.Instance[key];
After load() methid I have ClearCache method for easy developing (you know, once read, data is cached and you have to restart IIS Application Pool to refresh localization data).
Translator class is ready, I will show you how to use it later.


Create localization helpers

Create static class LocalizationHelpers and put it in "Helpers" folder in your project.

public static string CurrentCulture(this HtmlHelper html)
{
    return Translator.Instance.Locale;
}

public static string T(this HtmlHelper html, string key)
{
    return html.Encode(Translator.Instance[key]);
}

public static string T(this HtmlHelper html, string key,
    params object[] args)
{
    return html.Encode(string.Format(
        Translator.Instance[key], args));
}

I will use this in html views for translation like this

<%= Html.T("products") %>

If you want params in translated values you can use second T implementation like string.Format. First helper CurrentCulture is used in language select user control to determine current culture.

Create BaseController class

Create BaseController class that extends Controller and put it in "Infrastructure" folder of your MVC project. You should extend all your controller classes from this class. Create simple property for current selected culture (locale)

public string CurrentCulture
{
    get
    {
        return Translator.Instance.Locale;
    }
}

You will use this in your controller when you initialize your model, for example.
In the following code I will explain language detection and saving with cookie.


private void initCulture(RequestContext requestContext)
{
    string cultureCode = getCulture(requestContext.HttpContext);

    requestContext.HttpContext.Response.Cookies.Add(
        new HttpCookie("Culture", cultureCode)
        {
            Expires = DateTime.Now.AddYears(1),
            HttpOnly = true,
        }
    );

    Translator.Instance.Locale = cultureCode;

    CultureInfo culture = new CultureInfo(cultureCode);
    System.Threading.Thread.CurrentThread.CurrentCulture = culture;
    System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
}

private string getCulture(HttpContextBase context)
{
    string code = getCookieCulture(context);

    if (string.IsNullOrEmpty(code))
    {
        code = getCountryCulture(context);
    }

    return code;
}

private string getCookieCulture(HttpContextBase context)
{
    HttpCookie cookie = context.Request.Cookies["Culture"];

    if (cookie == null || string.IsNullOrEmpty(cookie.Value) ||
         !Translator.Cultures.Contains(cookie.Value))
    {
        return string.Empty;
    }

    return cookie.Value;
}

private string getCountryCulture(HttpContextBase context)
{
    // some GeoIp magic here
    return "en-US";
}

First I try to get language cookie if there is any (if this is not first time visit). If there is no cookie you can detect browser language, make GeoIP IP address lookup and so on. After finding some valid locale/culture I set response cookie for next page visits. After this I change current thread culture. This is useful if you want to format some date or currency values.
You should call initCulture in overridden Initialize method.


Changes in HomeController

Don't forget to change parent class of all your controller to BaseController. Add following code to your HomeController, so you can change current culture. When you open specified URL, a cookie is set and user is redirected to index page. This URL is like example.com/home/culture/en-US. Clear cache method is for deleting current cache without restarting application pool. Access it with example.com/home/ClearLanguageCache.

public ActionResult Culture(string id)

{
    HttpCookie cookie = Request.Cookies["Culture"];
    cookie.Value = id;
    cookie.Expires = DateTime.Now.AddYears(1);
    Response.SetCookie(cookie);

    return Redirect("/");
}

public ActionResult ClearLanguageCache(string id)
{
    Translator.ClearCache();

    return Redirect("/");
}

To change current language I will create special user control which will be included in may Master.Site layout. Create CultureUserControl.ascx and put it in Views/Shared/ folder of your MVC project. Here is the code:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>

<% if (Html.CurrentCulture() == "bg-BG") { %>
    <a id="lang" href="/home/culture/en-US">en</a>
<% } else { %>
    <a id="lang" href="/home/culture/bg-BG">bg</a>
<% } %>

In my layout I use <% Html.RenderPartial("CultureUserControl"); %> to include it.

Conclusion

In this simple tutorial I've created localization infrastructure for ASP.NET MVC web application. Translations of different languages are stored in XML files. Then I use Translator class to load them. Current user culture is kept in cookie. You can access Translator class in html views using some helpers. Also all the translation data i cached so it will not be loaded form XML every request.
Hope this tutorial helps.


Reasons why you must trust ASPHostPortal.com

Every provider will tell you how they treat their support, uptime, expertise, guarantees, etc., are. Take a close look. What they’re really offering you is nothing close to what ASPHostPortal does. You will be treated with respect and provided the courtesy and service you would expect from a world-class web hosting business.

You’ll have highly trained, skilled professional technical support people ready, willing, and wanting to help you 24 hours a day. Your web hosting account servers are monitored from three monitoring points, with two alert points, every minute, 24 hours a day, 7 days a week, 365 days a year. The followings are the list of other added- benefits you can find when hosting with us:

- DELL Hardware
Dell hardware is engineered to keep critical enterprise applications running around the clock with clustered solutions fully tested and certified by Dell and other leading operating system and application providers.
- Recovery Systems
Recovery becomes easy and seamless with our fully managed backup services. We monitor your server to ensure your data is properly backed up and recoverable so when the time comes, you can easily repair or recover your data.
- Control Panel
We provide one of the most comprehensive customer control panels available. Providing maximum control and ease of use, our Control Panel serves as the central management point for your ASPHostPortal account. You’ll use a flexible, powerful hosting control panel that will give you direct control over your web hosting account. Our control panel and systems configuration is fully automated and this means your settings are configured automatically and instantly.
- Excellent Expertise in Technology
The reason we can provide you with a great amount of power, flexibility, and simplicity at such a discounted price is due to incredible efficiencies within our business. We have not just been providing hosting for many clients for years, we have also been researching, developing, and innovating every aspect of our operations, systems, procedures, strategy, management, and teams. Our operations are based on a continual improvement program where we review thousands of systems, operational and management metrics in real-time, to fine-tune every aspect of our operation and activities. We continually train and retrain all people in our teams. We provide all people in our teams with the time, space, and inspiration to research, understand, and explore the Internet in search of greater knowledge. We do this while providing you with the best hosting services for the lowest possible price.
- Data Center
ASPHostPortal modular Tier-3 data center was specifically designed to be a world-class web hosting facility totally dedicated to uncompromised performance and security
- Monitoring Services
From the moment your server is connected to our network it is monitored for connectivity, disk, memory and CPU utilization – as well as hardware failures. Our engineers are alerted to potential issues before they become critical.
- Network
ASPHostPortal has architected its network like no other hosting company. Every facet of our network infrastructure scales to gigabit speeds with no single point of failure.
- Security
Network security and the security of your server are ASPHostPortal’s top priorities. Our security team is constantly monitoring the entire network for unusual or suspicious behavior so that when it is detected we can address the issue before our network or your server is affected.
- Support Services
Engineers staff our data center 24 hours a day, 7 days a week, 365 days a year to manage the network infrastructure and oversee top-of-the-line servers that host our clients’ critical sites and services.



About ASPHostPortal.com

We’re a company that works differently to most. Value is what we output and help our customers achieve, not how much money we put in the bank. It’s not because we are altruistic. It’s based on an even simpler principle. "Do good things, and good things will come to you".

Success for us is something that is continually experienced, not something that is reached. For us it is all about the experience – more than the journey. Life is a continual experience. We see the Internet as being an incredible amplifier to the experience of life for all of us. It can help humanity come together to explode in knowledge exploration and discussion. It is continual enlightenment of new ideas, experiences, and passions


Author Link


Corporate Address (Location)

ASPHostPortal
170 W 56th Street, Suite 121
New York, NY 10019
United States

Sign in