European ASP.NET MVC Hosting

BLOG about Latest ASP.NET MVC Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET MVC 4 Hosting - Amsterdam :: Error Handling and Logging in MVC4

clock April 2, 2013 10:19 by author Scott

Error handing is the main concern in any application, whether it is web application or desktop application. Usually, we catch the exception and log its details to database or text,xml file and also display a user friendly message to end user in-place of error.

Asp.Net MVC has some bulit-in exception filters. HandleError is the default bulit-in exception filter. Let's see how to use this filter with in your application.

HandleError Attribute

The HandleErrorAttribute filter works only when custom errors are enabled in the Web.config file of your application. You can enable custom errors by adding a customErrors attribute inside the <system.web> node, as shown below:

</system.web>
...
<customErrors mode="On" defaultRedirect="Error.htm"/>
</system.web>

HandleError Attribute can be used to handle error at Action Method level, Controller level and Global level.

HandleError Attribute at Action Method Level

Simply put this attribute to the action method to tell MVC how to react when an exception occurs.

[HandleError(ExceptionType = typeof(System.Data.DataException), View = "DatabaseError")]
public ActionResult Index(int id)
{
 var db = new MyDataContext();
 return View("Index", db.Categories.Single(x => x.Id == id));
}

In the above example when a database exception (System.Data.DataException) occurs during the execution of the Index action, MVC will display the DatabaseError view.

HandleError Attribute at Controller Level

Simply put this attribute to the controller to tell MVC how to react when an exception occurs with in the action methods of this controller.

[HandleError(ExceptionType = typeof(System.Data.DataException), View = "DatabaseError")]
public class HomeController : Controller
{
 /* Controller Actions with HandleError applied to them */
}

In the above example when a database exception (System.Data.DataException) occurs during the execution of the controler's any action methos, MVC will display the DatabaseError view.

HandleError Attribute at Global Level

You can also apply the HandleError Attribute for the entire application by registering it as a global error handler. For registering a global error handler, open the FilterConfig.cs file with in App_Start folder to find the RegisterGlobalFilters method.

By default, ASP.NET MVC template has already registered a global HandleErrorAttribute to the GlobalFilterCollection for your application. Here you can also add your own custom filter to the global filter collection as well.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
 filters.Add(new HandleErrorAttribute
 {
 ExceptionType = typeof(System.Data.DataException),
 View = "DatabaseError"
 }); 

 filters.Add(new HandleErrorAttribute()); //by default added
}

Note

Always remember, by default, global filters are executed in their registered order. so register error filters for specific exception types before any other.

You can also set the order of execution of these filter by giving number values to each. The above registered filters can be re-written as:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
 filters.Add(new HandleErrorAttribute(),2); //by default added
 filters.Add(new HandleErrorAttribute
 {
 ExceptionType = typeof(System.Data.DataException),
 View = "DatabaseError"
 },1);
}

Now, all the filters will be executed in the number sequence.

Limitation of HandleError Attribute

1. It has no support to log the exceptions since it suppressed the error once it is handled.
2. It only catch 500 Http error and doesn't catch other HTTP errors like 404,401 etc.
3. It doesn't catch the errors that occur outside the controllers like errors occurs in model.
4. It returns error view even if error occurred in AJAX calls that is not useful in the client-side. It would be great to return a piece of JSON in AJAX exceptions .

Extending HandleError Filter for logging and handling more errors

You can also make your custom error filter by extending HandleError filter. Let's see how to extend this filter to log the exceptions and return a JSON object for AJAX calls.

public class CustomHandleErrorAttribute : HandleErrorAttribute
{
 public override void OnException(ExceptionContext filterContext)
 {
 if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
 {
 return;
 }

 if (new HttpException(null, filterContext.Exception).GetHttpCode() != 500)
 {
 return;
 }

 if (!ExceptionType.IsInstanceOfType(filterContext.Exception))
 {
 return;
 }

 // if the request is AJAX return JSON else view.
 if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
 {
 filterContext.Result = new JsonResult
 {
 JsonRequestBehavior = JsonRequestBehavior.AllowGet,
 Data = new
 {
 error = true,
 message = filterContext.Exception.Message
 }
 };
 }
 else
 {
 var controllerName = (string)filterContext.RouteData.Values["controller"];
 var actionName = (string)filterContext.RouteData.Values["action"];
 var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);

 filterContext.Result = new ViewResult
 {
 ViewName = View,
 MasterName = Master,
 ViewData = new ViewDataDictionary(model),
 TempData = filterContext.Controller.TempData
 };
 }

 // log the error by using your own method
 LogError(filterContext.Exception.Message, filterContext.Exception);

 filterContext.ExceptionHandled = true;
 filterContext.HttpContext.Response.Clear();
 filterContext.HttpContext.Response.StatusCode = 500;

 filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
 }
}

 



European ASP.NET MVC 4 Hosting - Amsterdam :: How to Integrate Facebook Login button in ASP.NET MVC 4 application

clock March 15, 2013 07:06 by author Scott

This article demonstrates how to integrate login button on the web page in order to obtain access token that we'll need for further tutorials.

Visual Studio project setup

Firstly, let's get started by opening visual studio and creating new ASP.NET Mvc 4 Web Application. Name it FacebookLoginButton and make sure .NET Framework 4 is selected. Click on OK. Another window should now pop up asking for a type of tempalte you'd like to install in your app. Select An Empty ASP.NET MVC Project.

Once you've got your project created, right click on Controllers folder and Add Controller. Make sure controller name is set to HomeController.

What we need now is a view associated with home controller index method. To add a view, open newly created HomeController and look for a line where it returns View() ActionResult. View() should be highligted in red. Right click on it and select Add View.

Make sure you compile your project before editing anything. There is some problem with VS 2010 and MVC 4 Razor engine. When you try to edit .cshtml file without rebuilding your solution first, VisualStudio will crash.

Import and configure facebook javascript framework

Time for a little bit of javascript-ing. Buuu. Right click on Scripts and create new Javascript file. Name it Facebook.js. Paste in following content:

function InitialiseFacebook(appId) { 

    window.fbAsyncInit = function () {
        FB.init({
            appId: appId,
            status: true,
            cookie: true,
            xfbml: true
        }); 

        FB.Event.subscribe('auth.login', function (response) {
            var credentials = { uid: response.authResponse.userID, accessToken: response.authResponse.accessToken };
            SubmitLogin(credentials);
        }); 

        FB.getLoginStatus(function (response) {
            if (response.status === 'connected') {
                alert("user is logged into fb");
            }
            else if (response.status === 'not_authorized') { alert("user is not authorised"); }
            else { alert("user is not conntected to facebook");  } 

        }); 

        function SubmitLogin(credentials) {
            $.ajax({
                url: "/account/facebooklogin",
                type: "POST",
                data: credentials,
                error: function () {
                    alert("error logging in to your facebook account.");
                },
                success: function () {
                    window.location.reload();
                }
            });
        } 

    }; 

    (function (d) {
        var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
        if (d.getElementById(id)) {
            return;
        }
        js = d.createElement('script');
        js.id = id;
        js.async = true;
        js.src = "//connect.facebook.net/en_US/all.js";
        ref.parentNode.insertBefore(js, ref);
    } (document)); 

}

This javascript will ensure that we're subscribed to login event on which we'll submit fb access token to our controller and save it in session. Also, on each window load, we'll check for fb login status and alert user accordingly.

Sign up for an app

Now, go to developers.facebook.com and create a new app. Make sure all app's urls point to the actual address of the app. If you're running the app from Visual Studio, its address will be http://localhost:[PORT NUMBER].

Login model and controller

Next, we need to add account controller that will save facebook response in session. Before we add it, let's create a model for an object that we'll pass to account controller. Right click on Models folder and add FacebookLoginModel.cs (Class).

namespace FacebookLoginButton.Models
{
    public class FacebookLoginModel
    {
        public string uid { get; set; }
        public string accessToken { get; set; }
    }
}

Once we've got our model, we can add AccountController.cs.

using System.Web.Mvc;
using FacebookLoginButton.Models; 

namespace FacebookLoginButton.Controllers
{
    public class AccountController : Controller
    {
        [HttpPost]
        public JsonResult FacebookLogin(FacebookLoginModel model)
        {
            Session["uid"] = model.uid;
            Session["accessToken"] = model.accessToken; 

            return Json(new {success = true});
        } 

    }
}

Login button configuration

To enable facebook framework, make sure you've got following lines added to your Views -> Shared -> Layout.cshtml file. Following lines should be added just before body closing tag.

<div id="fb-root"></div>
    <script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/Facebook.js")"
type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            InitialiseFacebook(@System.Configuration.ConfigurationManager.AppSettings["FacebookAppId"]);
        });
    </script>

Finally, modify Views -> Home -> Index.cshtml by pasting in following code:

@{
    ViewBag.Title = "Part 1 - Facebook Login Button";    Layout = "~/Views/Shared/_Layout.cshtml";


<h2>Part 1 - Facebook Login Button</h2> 

<fb:login-button autologoutlink="true" perms="read_friendlists, create_event, email, publish_stream"></fb:login-button> 

<p>Facebook Access Token: @Session["accessToken"]</p>
<p>Facebook User Id: @Session["uid"]</p> 

<p>If you're not getting javascript prompts on each window load, make sure facebook app id in web config is correct.</p>

That's it. Feel free to download comleted solution attached to this post.

Done. Great job

 



European ASP.NET MVC 4 Hosting - Amsterdam :: ASP.NET MVC 3 and MVC 4 Routing

clock March 11, 2013 05:59 by author Scott

Basically, Routing is a pattern matching system that monitor the incoming request and figure out what to do with that request. At runtime, Routing engine use the Route table for matching the incoming request's URL pattern against the URL patterns defined in the Route table. You can register one or more URL patterns to the Route table at Application_Start event.

How to defining route...

public static void RegisterRoutes(RouteCollection routes)
{
 routes.MapRoute(
 "Default", // Route name
 "{controller}/{action}/{id}", // Route Pattern
 new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Default values for above defined parameters
 );


protected void Application_Start()
{
 RegisterRoutes(RouteTable.Routes);
 //To:DO
}

When the routing engine finds a match in the route table for the incoming request's URL, it forwards the request to the appropriate controller and action. If there is no match in the route table for the incoming request's URL, it returns a 404 HTTP status code.

See the picture below:

In above example we have defined the Route Pattern {controller}/{action}/{id} and also provide the default values for controller,action and id parameters. Default values means if you will not provide the values for controller or action or id defined in the pattern then these values will be serve by the routing system.

Suppose your webapplication is running on www.example.com then the url pattren for you application will be www.example.com/{controller}/{action}/{id}. Hence you need to provide the controller name followed by action name and id if it is required. If you will not provide any of the value then default values of these parameters will be provided by the routing system.

What is the Difference between Routing and URL Rewriting

Many developers compares routing to URL rewritting that is wrong. Since both the approaches are very much different. Moreover, both the approaches can be used to make SEO friendly URLs. Below is the main difference between these two approaches.

1. URL rewriting is focused on mapping one URL (new url) to another URL (old url) while routing is focused on mapping a URL to a resource.

2. Actually, URL rewriting rewrites your old url to new one while routing never rewrite your old url to new one but it map to the original route.



European ASP.NET MVC 4 Hosting - Amsterdam :: Seeding Membership &amp; Roles in ASP.NET MVC 4

clock March 5, 2013 06:44 by author Scott

Jon Galloway has an overview of the new membership features in ASP.NET MVC 4. The Internet project template moves away from the core membership providers of ASP.NET and into the world of SimpleMembershipProvider and OAuth.

There is quite a bit I could write about the new features and the code generated by the Internet project template, but for this post I just want to cover a scenario I've demonstrated in the past - seeding the roles and membership tables. If you are using Entity Framework code-first migrations it's relatively easy to add some code to the Seed method of the migrations configuration to populate the membership tables with some initial roles and users. Just remember every update-database command will call the Seed method, so you have to write the code to make sure you don't try to create duplicate data.

First, the new project template creates an MVC 4 Internet application without any provider configuration, but for the membership features to work properly during a migration, it appears you need at least some configuration. The following code makes sure the SimpleMembershipProvider and SimpleRolesProvider are in place.

<roleManager enabled="true" defaultProvider="simple">
 
<providers>
   
<clear/>
   
<add name="simple" type="WebMatrix.WebData.SimpleRoleProvider,
                             WebMatrix.WebData"/>
 
</providers>     
</roleManager>
<membership defaultProvider="simple">
 
<providers>
   
<clear/>
   
<add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider,
                             WebMatrix.WebData"/>
 
</providers>
</membership>

Then inside the Seed method of the DbMigrationsConfiguration<T> derived class, you can have:

protected override void Seed(MovieDb context)
{           
    //context.Movies.AddOrUpdate(...);

    // ...

    SeedMembership();
}

private void SeedMembership()
{           
    WebSecurity.InitializeDatabaseConnection("DefaultConnection",
        "UserProfile", "UserId", "UserName", autoCreateTables: true);
 
    var roles = (SimpleRoleProvider) Roles.Provider;
    var membership = (SimpleMembershipProvider) Membership.Provider;
 
    if (!roles.RoleExists("Admin"))
    {
        roles.CreateRole("Admin");
    }
    if (membership.GetUser("sallen",false) == null)
    {
        membership.CreateUserAndAccount("sallen", "imalittleteapot");
    }
    if (!roles.GetRolesForUser("sallen").Contains("Admin"))
    {
        roles.AddUsersToRoles(new[] {"sallen"}, new[] {"admin"});
    }
}



European ASP.NET MVC 4 Hosting - Amsterdam :: How to upload a file in MVC4

clock February 27, 2013 05:38 by author Scott

Uploading a file in Asp.Net MVC application is very easy. The posted file is automatically available as a HttpPostedFileBase parameters in the action of the controler. For uploading a file on the server you required to have a file input control with in html form having encoding type set to multipart/form-data. The default encoding type of a form is application/x-www-form-urlencoded and this is no sufficient for posting a large amount of data to server.

1. Form for uploading the file

@using (Html.BeginForm("FileUpload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
 @Html.ValidationSummary();
 <ol>
 <li class="lifile">
 <input type="file" id="fileToUpload" name="file" />
 <span class="field-validation-error" id="spanfile"></span>
 </li>
 </ol>
 <input type="submit" id="btnSubmit" value="Upload" />
}

2. Validating the file on client side

<script type="text/jscript">
//get file size
function GetFileSize(fileid) {
 try
 {
 var fileSize = 0;
 //for IE
 if ($.browser.msie)
 {
 //before making an object of ActiveXObject,
 //please make sure ActiveX is enabled in your IE browser
 var objFSO = new ActiveXObject("Scripting.FileSystemObject"); var filePath = $("#" + fileid)[0].value;
 var objFile = objFSO.getFile(filePath);
 var fileSize = objFile.size; //size in kb
 fileSize = fileSize / 1048576; //size in mb
 }
 //for FF, Safari, Opeara and Others
 else
 {
 fileSize = $("#" + fileid)[0].files[0].size //size in kb
 fileSize = fileSize / 1048576; //size in mb
 }
 return fileSize;
 }
 catch (e)
 {
 alert("Error is :" + e);
 }
} 

//get file path from client system
function getNameFromPath(strFilepath)
{
 var objRE = new RegExp(/([^\/\\]+)$/);
 var strName = objRE.exec(strFilepath);

 if (strName == null)
 {
 return null;
 }
 else
 {
 return strName[0];
 }
} 

$("#btnSubmit").live("click", function ()
{
 if ($('#fileToUpload').val() == "")
 {
 $("#spanfile").html("Please upload file");
 return false;
 }
 else
 {
 return checkfile();
 }
}); 

function checkfile()
{
 var file = getNameFromPath($("#fileToUpload").val());
 if (file != null)
 {
 var extension = file.substr((file.lastIndexOf('.') + 1));
 // alert(extension);
 switch (extension) {
 case 'jpg':
 case 'png':
 case 'gif':
 case 'pdf':
 flag = true;
 break;
 default:
 flag = false;
 }
 }
 if (flag == false)
 {
 $("#spanfile").text("You can upload only jpg,png,gif,pdf extension file");
 return false;
 }
 else
 {
 var size = GetFileSize('fileToUpload');
 if (size > 3)
 {
 $("#spanfile").text("You can upload file up to 3 MB");
 return false;
 }
 else
 {
 $("#spanfile").text("");
 }
 }
} 

$(function ()
{
 $("#fileToUpload").change(function () {
 checkfile();});
});
</script>

3. Controller's action for receiving the posted file

[HttpPost]
public ActionResult FileUpload(HttpPostedFileBase file)
{
 if (ModelState.IsValid)
 {
 if (file == null)
 {
 ModelState.AddModelError("File", "Please Upload Your file");
 }
 else if (file.ContentLength > 0)
 {
 int MaxContentLength = 1024 * 1024 * 3; //3 MB
 string[] AllowedFileExtensions = new string[] { ".jpg", ".gif", ".png", ".pdf" };

 if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf('.'))))
 {
 ModelState.AddModelError("File", "Please file of type: " + string.Join(", ",
AllowedFileExtensions));
 }

 else if (file.ContentLength > MaxContentLength)
 {
 ModelState.AddModelError("File", "Your file is too large, maximum allowed size is: " + MaxContentLength + " MB");
 }
 else
 {
 //TO:DO
 var fileName = Path.GetFileName(file.FileName);
 var path = Path.Combine(Server.MapPath("~/Content/Upload"), fileName);
 file.SaveAs(path);
 ModelState.Clear();
 ViewBag.Message = "File uploaded successfully";
 }
 }
 }
 return View();
}

How it Works

 



European ASP.NET MVC 4 Hosting - Amsterdam :: Bundling and Minification of JavaScript and CSS ASP.NET MVC 4

clock February 8, 2013 05:32 by author Scott

ASP.NET MVC 4 beta has built in minification, which reduces the number of requests and general payload size, resulting in faster and better performing applications.

This feature allows you can create custom bundles where you specify the resource name and order of your stylesheets and JavaScript files.

Introducing ASP.NET MVC 4 BundleTables

Upon creating a new project in ASP.NET MVC 4, you'll notice that your default _Layout.cshtml file will reference System.Web.Optimization and BundleTable.Bundles in its head.

According to Microsoft, these references are for the beta and will be accessed via a helper in the RTM release, expected sometime next quarter.

<link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/css")" rel="stylesheet" type="text/css" />
<link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/themes/base/css")" rel="stylesheet"    type="text/css" />
<script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")"></script>

If you look at the actual source code in the browser, you will see these get rendered as:

<link href="/Content/css?v=x" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/css?v=y" rel="stylesheet" type="text/css" />
<script src="/Scripts/js?v=z"></script>

The CSS and JavaScript files in this project are minified and compressed and the querystring parameter, v, is a hash of the current files being served. This will change when you alter your .js and .css files.



About HostForLIFE

HostForLIFE 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 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Month List

Tag cloud

Sign in