ASP.Net MVC4 – Suraj | Coding Passion Tue, 09 Oct 2018 07:03:49 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.8 Export an Excel file using ClosedXML /create-an-excel-file-using-closedxml/ /create-an-excel-file-using-closedxml/#comments Mon, 06 Jun 2016 12:48:10 +0000 /?p=659 Introduciton

In today’s tech world, most of the applications being developed under Logistics, Inventory, Internal Transaction and other domains require day-to-day data in excel files and prefer excel file operations in their applications.
I will be sharing one of the Nuget Package tool, which wil very minimal lines of code will export an excel file for us.
The Tool is Closed XML.
1
Just write a few lines of code and done! It is developer friendly. If we have used the Open XML, there are a lot of lines of code which are required to export an excel fron data. We can create excel file of 2007/2010 configuration without even Excel application.
To add the closed XML package, we add directly through the user interface, from the Nuget Gallery and also, we can use the Package Manager console to add the package using the below command

PM> Install-Package ClosedXML

Snippet!

DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[3] { new DataColumn("Id", typeof(int)),
            new DataColumn("Name", typeof(string)),
            new DataColumn("Country",typeof(string)) });
            dt.Rows.Add(1, "C Sharp corner", "United States");
            dt.Rows.Add(2, "Suraj", "India");
            dt.Rows.Add(3, "Test User", "France");
            dt.Rows.Add(4, "Developer", "Russia");
            //Exporting to Excel
            string folderPath = "C:\\Excel\\";
            if (!Directory.Exists(folderPath))
            {
                Directory.CreateDirectory(folderPath);
            }
            //Codes for the Closed XML
            using (XLWorkbook wb = new XLWorkbook())
            {
                wb.Worksheets.Add(dt, "Customers");

                //wb.SaveAs(folderPath + "DataGridViewExport.xlsx");
                string myName = Server.UrlEncode("Test" + "_" + DateTime.Now.ToShortDateString() +          ".xlsx");
                MemoryStream stream = GetStream(wb);// The method is defined below
                Response.Clear();
                Response.Buffer = true;
                Response.AddHeader("content-disposition", "attachment; filename=" + myName);
                Response.ContentType = "application/vnd.ms-excel";
                Response.BinaryWrite(stream.ToArray());
                Response.End();
            }

The above code, instantiates a data table, with few data initialization.

public MemoryStream GetStream(XLWorkbook excelWorkbook)
        {
            MemoryStream fs = new MemoryStream();
            excelWorkbook.SaveAs(fs);
            fs.Position = 0;
            return fs;
        }

We are using this method, so as to return a stream inorder to download the file in response using the stream. The save as method of the Closed XMl, helps create the stream.
Downloaded file looks like below:
2

Conclusion

Here, I have shared the code where hard coded values are added, this is not the case everytime. We can always use the records from the database and create them as a datatable and then use the Closed XML. This really reduces a lot of codes which is used in Open XML package. So, developers try it!! I will be sharing another article where I would show, how to Import the same exported excel file using Bulk copy using SQL Bulk copy.

]]>
/create-an-excel-file-using-closedxml/feed/ 3
Lets Chat Application using SignalR in MVC /lets-chat-application-using-signalr-in-mvc/ /lets-chat-application-using-signalr-in-mvc/#comments Sat, 16 Apr 2016 19:48:40 +0000 /?p=590 Download Source Code

Introduction

Here I would be demonstrating an application to chat and chat private as well, using SignalR.
Before that we need to know first what is SignalR! SignalR is an open and free library which can be used to have real-time functionality integrated to your web applications. There are a hell lot of areas where SignalR can come handy to make your application more handy and more integrated and more responsive to the end user as well. Real-time means having your server respond as quick as possible to the client as and when a request is made.
Now, take for an instance, we have a requirement to show the user uploading a file, the percentage of that file been uploaded on the server. Or I had come across a scenario where, we had to show the end user, who would be uploading a CSV file with ‘n’ number of rows and process each row for some validations. End user would be wondering what would be going on in the back-end. So, would it be great if we could show him how many rows have been processed and how many are left out! Similar to a progress window. Here, comes the SignalR magic!
Most of us think SignalR would be useful in making chat applications, but NO!,it has much more than just chat! I don’t think the makers of SignalR would have a thought in mind to make a chat application out of it! 😛
Much of a story now! Lets get into a bit of theory!

Theory

We will look into a simple image below and from that image we will try and gain some knowledge on the flow:
1
Now a days, every application requires a load of server response in the real time to sustain in the market, as the user expectations have raised high.
Remote Procedure Calls (RPC) is the concept that takes place in the SignalR internally. SignalR provides an API which helps in making the RPC between the server and the client. Actually, from the client side, server side functions are called using JavaScript, once the connection to server is set. The SignalR API also helps creating connections and manage them when required. In simple terms, SignalR provides connection between server and client, letting server to call the funcitons on the client side and from the client side, calling the server side. That somehow is called “Server-Push”.
SignalR starts with HTTP and then to a WebSocket if connection is available. From Wiki,
“WebSocket is a protocol providing full-duplex communication channels over a single TCP connection.”
An advantage of using WebSocket is it can be used by both client and server applications. WebSocket is considered to be the most efficient and consistent medium of communication as, it has the ability to manage server memory in a proper manner and being a full duplex communication, has low latency. These are the considerations made with SignalR which make it more efficient.
The SignalR decides the transport based on the browser, i.e. if the browsers support the kind of transport required by the SignalR. We will discuss the kinds of transports next:

HTML 5 Transports

  • WebSockets as we have already discussed. This transport is considered to be true-persistent, creating a two way connection between client and server if the browsers support.
  • Server Sent events also called Event Source, which is supported by all browsers except IE.

Comet Transports

Comet usually,is a web application model in which a long-held HTTP request allows server to post data to a client (browser).

  • Forever frame This is supported by Internet Explorer only. Creates a hidden frame making a request to endpoint on the server. Server keeps pinging client or sends script to the client, thus providing a one way connection, creating a new connection on every request.
  • Ajax Polling This is actually long polling, which is never persistent. This polls the request and waits until and unless the response is received from the server. This introduces latency and the connection resets.

Practical

We will be creating a chat application in order to explain the flow of SignalR. We install the SignalR, create a hub to which the client will interact, calling the server methods and in return the server responds and interact with the client.
You can directly add a new project in VS for the SignalR or create an MVC project and install the SignalR package/libraries from the Nuget.

PM > Install-Package Microsoft.AspNet.SignalR

This is download all the dependencies required for the SignalR.
2

After the successful installation, the above dll’s or packages are installed into your project.
There will be a class file which needs to be added to the root of your project, which would look like:

using Owin;
using Microsoft.Owin;
[assembly: OwinStartup(typeof(SignalRChat.Startup))]
namespace SignalRChat
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
        }
    }
}

This is OWIN based applicaiton. Every OWIN application will have a startup.cs class, where the component for the application pipeline are added. The OWIN attribute which specifies the type of property, specifying the project’s start up and the configuration method, sets up the SignalR mapping for the App.
There will be another two script files that would be added as we install the packages for SignalR.
3
These script files are mandatory to be loaded onto the .cshtml page in order to activate the SignalR.
Lets look into the code straight away:
We need to add a new hub class inside a Hub folder. Lets name that LetsChatHub.cs, which would look like:
hub

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;

namespace LetsChatApplication.Hubs
{
    public class LetsChatHub : Hub
    {
        public void Send(string name, string message,string connId)
        {
            Clients.Client(connId).appendNewMessage(name, message);
        }
    }
}

The above send method accepts the parameters, name (which you would be giving once you navigate onto the url), the message (which the user would be sending from the UI). The other parameter is connId, which would help us have chat private and not send to every user who navigates to the site. If you would like to have every user receive and send the messages who navigates to the URL. To allow every users the access, the code you change as below:

namespace LetsChatApplication.Hubs
{
    public class LetsChatHub : Hub
    {
        public void Send(string name, string message)
        {
            Clients.All.appendNewMessage(name, message);
        }
    }
}

The Send method, is requested from the client with the parameters after the connection is set on the client side and once the server receives the request, it processes and sends back the response to the client, using the appendNewMessage. This appendNewMessage method is added on the client side to receive the response and display on the UI to the client.
You need to add a controller, lets suppose: “LetsChat” with an action “LetsChat”, add a view to that with the below code to it.
The client side code would look like below:

@{
    ViewBag.Title = "LetsChat";

}


<h2>Lets Chat</h2>
<link href="~/Content/sweetalert.css" rel="stylesheet" />

<div class="form-group col-xl-12">
    <label class="control-label">Your connection Id</label><br />
    <input type="text" class="col-lg-12 text-primary" id="frndConnId" placeholder="Paste your friend's connection Id" /><br /><br />
    <label class="control-label">Your Message</label><br />
    <textarea type="text" class="col-lg-10 text-primary" id="message"></textarea>&nbsp;&nbsp;&nbsp;&nbsp;

    <input type="button" class="btn btn-primary" id="sendmessage" value="Send" /><br /><br />
    <img src="~/Content/smile.jpg" width="20" height="20" id="smile" style="cursor:pointer"/>
    <img src="~/Content/uff.jpg" width="20" height="20" id="ufff" style="cursor:pointer" />
    <div class="container chatArea">
        <input type="hidden" id="displayname" />
        <ul id="discussion"></ul>
    </div>
</div>
<br />
<input type="hidden" id="connId" />

<!--Reference the autogenerated SignalR hub script. -->
@section scripts {
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Content/sweetalert.min.js"></script>
    <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
    <script src="~/signalr/hubs"></script>
    <script>
        //var userName = "";
        //var sessionVal = '';
        $(function () {
            // Reference the auto-generated proxy for the hub.
            var chat = $.connection.letsChatHub;
            
            debugger;

            // Create a function that the hub can call back to display messages.
            chat.client.addNewMessageToPage = function (name, message) {
                // Add the message to the page.
                $('#discussion').append('<li><strong>' + htmlEncode(name)
                    + '</strong>: ' + htmlEncode(message) + '</li>');
            };
            // Get the user name and store it to prepend to messages.
            swal({
                title: "Lets Chat!",
                text: "<span style='color:#f8bb86;font-weight:700;'>Enter your name:</span>",
                type: "input",
                html: true,
                showCancelButton: true,
                closeOnConfirm: true,
                animation: "slide-from-top",
                inputPlaceholder: "Your Name"
            },
            function (inputValue) {
                userName = inputValue;
                if (inputValue === false) return false;
                if (inputValue === "") {
                    swal.showInputError("You need to type your name!");
                    return false;
                }
                $('#displayname').val(inputValue);
            });
            // Set initial focus to message input box.
            $('#message').focus();
            $('#message').keypress(function (e) {
                if (e.which == 13) {//Enter key pressed
                    $('#sendmessage').trigger('click');//Trigger search button click event
                }
            });
            $("#smile").click(function () {

            });
            // Start the connection.
            $.connection.hub.start().done(function () {

                $('#sendmessage').click(function () {
                    // Call the Send method on the hub.
                    var connId = $("#connId").val();
                    var frndConnId = $("#frndConnId").val();
                    var finalConnId = frndConnId == "" ? $.connection.hub.id : frndConnId;
                    chat.server.send($('#displayname').val(), $('#message').val(), finalConnId);
                    $("#connId").val($.connection.hub.id);
                    if (frndConnId == "") {
                        swal("You connection Id", $.connection.hub.id, "success");
                    }
                    // Clear text box and reset focus for next comment.
                    $('#discussion').append('<li><strong>' + htmlEncode($('#displayname').val())
                   + '</strong>: ' + htmlEncode($('#message').val()) + '</li>');
                    $('#message').val('').focus();
                });
            });
   
        });
    // This optional function html-encodes messages for display in the page.
    function htmlEncode(value) {
        var encodedValue = $('<div />').text(value).html();
        return encodedValue;
    }
    </script>
}

Lets Chat

We have a normal UI in place to add your message and send button to call the server methods.
Lets understand the code above part by part.

var chat = $.connection.letsChatHub;

Here, we set the connection to the Hub class. As you can notice here, letsChatHub, is the same hub class file name which we added to set up the server. The convention as follows, the intial of the methods or the class name starts with lowercase. From here, we use chat to access the Send method.

$.connection.hub.start().done(function () {
                $('#sendmessage').click(function () {
                    // Calls the Send method on the hub.
                    chat.server.send($('#displayname').val(), $('#message').val(), finalConnId);

chat.server.send,is self explanatory, it sets the chat connection to call the server Send method once the connection is set and started.

chat.client.appendNewMessage = function (name, message) {
//
}

This is called, when the Server receives the request and calls back the method on client side.

How the sample would work!

The sample provided for download, will be having few instructions to follow:

  • When you navigate to the LetsChat/LetsChat route, an alert would pop up asking you for the name with which you would like to chat. Sweet Alert !!
    5
  • Once you enter the name, you see a textbox which asks you for “Your friend’s connection Id”, but since you are starting the chat, you just send a message, and another pop up comes up, with your connection ID, which you need to share with your friends to share your message. Remember, only those who have your ID use it while chatting will be able to see and send through messages to you.
    6
  • When you friend navigates, he ought to generate his connection ID and share with you inorder to set up your connection completely. Thus, you need to have the connID to whom you will be sending and vice-versa with your friend as well. Then just chat!! 🙂
    7

If you would want to send message to all and make that common, then use the Clients.All code snippet to send all.
Another interesting thing, which was figured out is, the use of @section scripts{}, that lets the Signal R scripts render and active on your page and also using the @section scripts provides your code a good outlook.

Share and Send files using SignalR!!

Ooops!! Nice question right!
It is ideally not advised, rather I would not recommend to send or share files using Signal R. There always is better way to accomplish that. The idea would be using API, you can have an upload area, and use SignalR to show the progress and once upload completes, update the user regarding the completion and generate a download link on the UI for the users to download and view the file.
This is not always the best idea, but is just another idea. 🙂

Conclusion

This is just a simple Chat application, which you can use to chat with your friends, if you host on Azure or any other domain. But again,SignalR is not just this much. There is a lot of other effective use of SignalR. Will be sharing more utility of SignalR in few articles more.

References

Asp.Net
Asp.Net|SignalR

]]>
/lets-chat-application-using-signalr-in-mvc/feed/ 1
Unobstrusive ajax and handle unauthorized request in MVC /unobstrusive-ajax-and-handle-unauthorized-request-in-mvc/ /unobstrusive-ajax-and-handle-unauthorized-request-in-mvc/#respond Tue, 05 Apr 2016 10:18:26 +0000 /?p=580 Introduction

In this article I will be sharing a basic stuff which comes handy in MVC applications. The HTML helpers provided by the Razor are smart enough to understand and process the work as required.
We will be discussing in brief about the Ajax.BeginForm, which has few concepts hidden within. When we face the difficulty or the issue, we explore and resolve. Same has happened recently with me. So lets start exploring what the hidden secrets are, which actually are very few.

Adding Unobstrusive- Ajax JS

This can be added from the Nuget package manager directly. I find adding from the Package Manager console easy. The script goes like below:

Install-Package jQuery.Ajax.Unobtrusive

Snippet & Learning

AjaxExtensions.BeginForm is a part of System.Web.Mvc.Ajax namespace under the System.Web.MVC assembly. When used in the response it writes the HTML

tag. Ajax, as we know is Asynchronous Javascript and XML, the word asynchronous plays the trick actually. That means the call will be done asynchronously in some other thread, without hampering or halting the current executing thread for better user experience and performance. Thus, the ajax call we used to write through jQuery, can be done by the MVC HTML helpers now.
One important point to remember here is we need to have the unobstrusive-ajax.js file in order for the Ajax.BeginForm to work in the actual manner.
The Ajax.BeginForm has three options attached to it.
@using (Ajax.BeginForm("ACTION", "CONTROLLER", new AjaxOptions { UpdateTargetId = "TARGETID" ,OnSuccess="PostSuccess"}))
{
   <div id="TARGETID"></div>
   // Do anything you would like to.
}

Lets understand the properties it possesses.
The first param to the Ajax.BeginForm is Action Method, the action to which we will be posting or getting the results.
The second param is Controller, the route controller in which the Action Method is specified. The route table in turn configures accordingly.
The third is the important property of the Ajax.BeginForm as it gives us the different options in order to track and show the response, even manipulate the response as well.

  • UpdateTargetId:- This property is used to track the ‘id’ where the ajax response will be displayed.
  • OnSuccess, OnFailure, OnComplete, OnBegin:- The second part of the option is the track functions. We can use the the functions to track the event and update the UI accordingly. The methods are self explanatory so, I not being stupid to explain the same. 😛
  • HttpMethod:- This again is self explanatory, it allows the POST GET to be specified explicitly.
  • AllowCache:- This method in ajax allows to either cache the response or not. By default it caches the identical request’s response. So to avoid any kind of caching, we can use the Attribute [OutputCache(NoStore = true, Duration = 0, VaryByParam = “*”)]

These were few of the important properties discussed, which are frequently used.
Now another issue we face is when we have a session ended for any user, but the user is still on the web page, then we find that the login page loads in the partial part of the page only, not the whole page is reloaded to the Login page, which is really weird from any user point of view. This can easily be done and accomplished by changing the UpdateTargetId to the body or supplying any id to the body tag.
But sometimes we have to handle the unauthorized access from the user during any ajax calls. So, incase (everytime now in MVC projects Authorize attribute and its virtual methods are overridden), inside the Custom Authorize attribute, we modify/override the HandleUnauthorizedRequest and handle the Ajax calls that are unauthorized. The code goes below:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.Result = new JsonResult
                {
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                    Data = new { redirectTo = FormsAuthentication.LoginUrl }
                };
            }
            else
            {
                base.HandleUnauthorizedRequest(filterContext);
            }
        }

filterContext.HttpContext.Request.IsAjaxRequest() is doing the trick here, tracking whether the request coming from the client is Ajax request or the normal request.
redirectTo = FormsAuthentication.LoginUrl This takes the default login URL from the app settings in Web.config file. Thus now the result of the context will be present in the current context and can be tracked by the Onsuccess method. The code can be seen below:

function PostSuccess(result) {
    if (result.redirectTo) {
        window.location.href = result.redirectTo;
    }
}

This is a simple part, we can also do the same tracking the reference of the result context and manipulate.

Conclusion

I tried to cover a basic stuff in the MVC application, which we use frequently in our application, sometimes scratch our head to get a proper understanding and solution to a simple problem. I hope this has helped some way. Any suggestions or more interesting facts are more than welcome.
Keep learning and keep sharing.

]]> /unobstrusive-ajax-and-handle-unauthorized-request-in-mvc/feed/ 0 Working with JSON in MVC /working-with-json-in-mvc/ /working-with-json-in-mvc/#respond Fri, 01 Apr 2016 19:05:10 +0000 /?p=547 Introduction

JSON Java Script Object Notation , a very familiar and commonly used concept. It is a data interchange medium and is very lightweight. It is one kind of a syntax for storing and passing data. Since it is Java script object notation, it uses the java script style of syntax, but actually is text only. It also is language independent. The format would look like below:

{"Books":[
    {"name":"Asp.Net Mvc", "code":"111"},
    {"name":"Angular Js", "code":"112"},
    {"name":"Javascript", "code":"113"},
    {"name":"CLR", "code":"114"}
]}

Now this, JSON object can be created and used to POST or GET in MVC application. Usually, when we do an ajax call, we get the HTML fragments and send them to the browser or append to any DOM elements. That is acceptable, but sending HTML elements with data is not advisable, so would not that be great to send data in a specific format and the browser assigns the data into the HTML. Here, JSON comes in handy. Lets see how. I will explain in simple terms and snippets for better understanding as this topic is not complex at all.

Peek into Snippets!!

I will proceed with an anticipation that readers are aware of MVC (Model, View & Controller), as I will not be sharing the steps to create an MVC project. So, Lets start.
When we create a controller in an MVC project, we know the default type added is ActionResult, which is generic to other types of method types pre-defined like: ViewResult, JsonResult, etc.. Thus, for returning a JSON data, we can use either ActionResult or JsonResult,but preferably use JsonResult as we already know the type, the method will return. JsonResult, is actually a special ActionResult, which suggests the ViewEngine that an object of JSON type will be returned rather than normal HTML.
Lets see the snippet and then try and understand.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.MVC;
using DemoJsonTest.Models;

namespace DemoJsonTest.Controllers {
    public class EmployeeController : Controller {
        private Employee[] employeeData = {
            new Employee {Name:"Suraj Sahoo",EmpCode:"EMP042"},
            new Employee {Name:"Suraj Sharma",EmpCode:"EMP044"},
            new Employee {Name:"Suraj Ray",EmpCode:"EMP041"}
        };

    public ActionResult Index() {
        return View();
    }
   
    public JsonResult GetEmployeeDataJson(string empCode) {
        var employee = employeeData.Where(emp =&gt; emp.EmpCode == empCode).SingleOrDefault();
        return Json(employee, JsonRequestBehaviour.AllowGet);
    }

Thus,in the above code, we have shown a normal controller, in whose constructor we have explicitly initialized a model named Employee with few dummy data. Then the main part is the JsonReult method using which, we are filtering the data based on the parameter passed, here EmpCode and then returning the Json object. Mark here, we have used JsonRequestBehaviour.AllowGet. Now whats this. This has an interesting concept behind it. Usually, the browsers to avoid malicious sites trying to intercept JSON data returned, in response to a GET request, it does not respond to GET requests by default.

System.InvalidOperationException: This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.

The above is a part of the error thrown when we miss AllowGet. That is self explanatory actually. 😛
We usually us ajax options, i.e. success method to process the JSON data received from the GET request and append or set to the HTML DOM elements.

<script type="text/javascript">
$.ajax({
    url: "GET REQUEST URL",
    type:"GET",
    success: function(empData) {
            var trgt = $("#tblEmployee");
            target.append("<tr><td>" + empData.Name + "</td><td>" + empData.EmpCode + "</td></tr>");
        },
    error: function() {
      //Do something..
        }

});
// ]]></script>

Thus, in the above snippet, we are fetching the data in JSON format from the GET response and binding to the table html dom.
A point to note here is that, when we assign/cast (actually) a model into JSON object and we explicitly specify few properties of the model and miss out on others, MVC framework is clever enough to first convert the model with each property into JSON and then assign default values to those properties which we have missed. Lets see an example of conversion:

{ "EmployeeId":0, "Name":"Suraj Sahoo", "EmpCode":"042",
     "IsActiveEmployee": false, "DepartmentId": null }

Mark here,that we have only specified the values of Name and the EmpCode, all other values assigned after JSON conversion by the MVC smart framework.

Conclusion

We saw and discussed a very simple and interesting topic regarding the JSON in MVC and how smartly MVC handles the conversion. This helps when we use API and then return JSON,XML to interchange and expose our data. JSON is actually an alternative to XML form of data exchange. For angular JS now a dayswhich is in demand,we use the API controller, return JSON data and take the advantage of Angular two-way binding.
I hope this helps the beginners out there learning MVC. This is a part of it. Enjoy coding. Open to suggestions. Don’t miss to add your feedback. 🙂

]]>
/working-with-json-in-mvc/feed/ 0
Url routing in MVC application /url-routing-in-mvc-application/ /url-routing-in-mvc-application/#comments Sun, 27 Sep 2015 10:04:55 +0000 /?p=419 Introduction

There exists an assumption that there is a direct relationship between the requested URLs and the files stored on the server. But does this make sense in an MVC application, where requests are processed by action methods and controllers and there is no relation to files on the server (disk).
MVC applications use routing system in order to track the request and give response to the users. The routing system helps create patterns of URLs, that to pattern of our wish. The routing system does the following job, Incoming URL examination- It checks the url requested and it intends the controller and action and based on the url, it redirects the controller based on the client request. This is a very interesting and an important subject of discussion. Once we create an MVC application, it is already configured to use Asp.Net routing system. There are four sections that are any way required relevantly for the routing system in the application. They are:

  • system.web httpModules:- These are required to configure the modules within an application. Http Modules are assemblies that are called on every request made to the application.
  • system.web.httpHandlers:- This runs in response to the request made to the application.

The above mentioned are required for the routing system and should be present in the configuration of the application. We need to make sure the above configurations exist in our application.

Lets start with snippets

public class RouteConfig {
    public static void Registerroutes (RouteCollection routes) {
         routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
         routes.MapRoute (
            name : "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

Now, this RouteConfig.cs resides inside the App.Config folder. The RegisterRoutes method inside the RouteConfig.cs gets called from the heart of the MVC application i.e. Global.asax.cs, which sets the core MVC features when the application is started. The called RegisterRoutes method gets called inside Global.asax.cs as follows:

RouteConfig.RegisterRoutes(RouteTables.Routes);

To the method as we can see the parameter is passed i.e. RouteTables.Routes which is a collection routes or the instance of the RouteCollection.cs. To register adding a new route, we need to register inside the RegisterRoutes method as below:

Route demoRoute = new Route("{controller}/{action}", new MvcRouteHandler());
routes.Add("DemoRoute", demoRoute);

Lets understand the above snippet, Here a new route named demoRoute is being created. MvcRouteHandler() is also passed to the constructor. This extends the IHttpHandler and passes the request. routes , the object above is an instance of the RouteCollection class which is passed from the Global.asax.cs. There is another easy way of registering routes, i.e. by using MapRoute method defined by RouteCollection class like below:

routes.MapRoute("RouteName", "{controller}/{action})

One thing to note here is, if the route incase donot match any of the routes in the RouteCollection, then the error is thrown to the user. generally, default route is set to Index as action. Then, the url with https://demosite/home will also get the user to the Index action method. If both the controller and action are provided to the routes, then routes match url with no segments (if default is defined in the RouteConfig). Generally, the controller if only used in the url, then the Controller’s action Index method is called i.e.

https://demosite.com/Admin

This would call the Admin Index method. If any other action method is called, then similarly based on the segments in the url requested, the action in the specified controller is called.

Static URL Segments

There is this concept of static url segments. This is rarely used but the concept is quite interesting. Here, the route is registered inside RouteConfig like below:

routes.MapRoute(""), "X{controller}/{action}");

Here, what happens is whatever is present after X or suffixed to X, that controller and action gets called. For example, https://demosite.com/XAdmin/Index, here what happens is the controller Admin and the Action Index is called.
There is a concept of Route Ordering as well, in which in the order the routes are defined in the RouteCollection, the same order the route mapping is done. I.E. when a URL requests is made to the application, the route config maps the route defined until a match is found in the same order routes are defined.
Another interesting fact to notice here, Suppose we have a controller named “Admin” and sometime in the future we require to modify the name of that controller. Now if we donot modify our RouteConfig, we would get a 404 NOT FOUND error. To avoid this we do the following modification in the Route.Config.cs:

public static void RegisterRoutes (RouteCollection routes) {
   routes.MapRoute ("Admin","Admin/{action}",
      new {controller="Home"});
  }

Thus, when a request as /Admin/Index comes to the server, the controller called is /Home/Index, avoiding the 404 error page. Since, there is no segment variable supplied, so default provided is used. The same can be done in case of an Action as well, i.e. if an action is removed from the controller, we can have a default route check for that action as well and redirect to the specified and default route URL if not found. Like as below:

routes.MapRoute("Admin","Admin/department",
    new {controller = "Admin",action = "Index"});

Defining Custom Segment Variables

Controller and Action are common part of any url request to the MVC application and these would be considered as the in-built segment variables. But there are other segment variables that can be customized for the service requests. Lets take a look at a snippet:

public static void RegisterRoutes(RouteCollection routes) {
    routes.MapRoute("RouteDemo", "{controller}/{action}/<b>{id}</b>")
        new {controller = "Admin" , action="GetDept", id = "DefaultID"});
}

Here we can see we have declared a custom varialble “id” with a default value. Thus any url request with two or three segment variables would work out. If the id is not specified explicitly in the URL, then it takes the default id value.
Usually,the third segment variable is used to fetch the parameter to be utilized in the service methods.

public ActionResult GetDepartment(int id) {
  //Used id to get the particular department.
}

Here if id is not provided in the URL, then it searches using default id specified and may return null. Thus, to avoid, we can also defined the third segment variable to be optional, so that we have action to also return result if no id is specified in the URL.

routes.MapRoute("OptionalRoute", "{controller}/{action}/{id}",
     new {controller = "Admin", action = "GetDept", id = <b>UrlParameter.Optional</b> });

Thus the UrlParameter.Optional makes the third segment variable optional and rund through without any default variables as well.

Prioritizing Controllers with same name using name spaces

This is a very interesting and strong concept which can be really handy, when working on a huge MVC application. Lets take a scenario to understand this, suppose we have a controller name “Home “inside the controllers folder and another controller with same name “Home” inside another folder say “AddonControllers”. So when we run the project and hit the URL /Home/Index, then the routing and mapping that searches the URL requested, will be in ambiguity as it fetches two controllers with same names. Thus this will throw an error with the exception message as :

Multiple types were found that match the controller named “Home”. This can happen if the route that services this request (‘{controller}/{action}/{id}’) does not specify the namespace to search for a controller that matches the request..

Thus, from the error message itself we can get that this error can be resolved easily by specifying the name space for which you want to prioritize the search when URL request is made to the server. Lets see how:

routes.MapRoute("DemoRoute", "{controller}/{action}/{id}",
      new {controller = "Home", action = "Index", id = <b>UrlParameter.Optional</b> },
       <b> new []{"URLsAndRoutes.AddonControllers"}</b>);

Here, specifying the new array of strings and saying the MVC routing to search for the controller everytime in the AddonControllers or the specified namespace first and if not found then move into the controllers folder to search for the match of the URL request. This really would of high use when the requirement is as such.

Conclusion & Points of Interests

Thus here we discussed about one of the critical concepts of MVC. Routing and pipelining is a mandatory concept to know to start with learning MVC. using MVC application and not using Routing is not wise. There are opportunities to manipulate and customize the Routing system, so it is always advisable to use Routing whenever MVC application is in picture. The URL segment variables Controllers, Actions and parameters are required to customize the URLs to th convinience of the end users. The routing can narrow down the search of the routes if the maximum hit URL requests are ordered highly in the Route Collection.

References

Asp.NET MVC Professional by Adam Freeman.

]]>
/url-routing-in-mvc-application/feed/ 1
Validation & Security in MVC application /validation-security-in-mvc-application/ /validation-security-in-mvc-application/#respond Sun, 06 Sep 2015 16:32:15 +0000 /?p=407 Introduction

Validations in any application is so critical now a days that developers ought to be on their toes while developing any such critical and sensitive applications. Hackers are now in every corner of the society, avoid them restrict them to post non sense data into your applications. The attacks are so vulnerable that security guard of any application is mandatory.
security1
The security checks and implementations should be alert and active in the application to counter the attacks. Lets start learning about different types of validations we can have in our MVC application.

Server-Side Validation

Lets begin with simple server side validations. Server side validation are required when we post something to the server with an expectation for the response,usually while posting form data. The form data post is generally very vulnerable. The attacks are quite easier for the attacker here. Thus, we need to check on the server if we are receiving valid data or not on our end. Thus, server side validation can to some extent prevent nonsense input data. Lets discuss how to do validation explicitly using view model. Lets discuss how:
Explicitly means, we would be checking on server side after form post by the user, if the data input are valid input or not, then we post back the user with the validation message as response.
Suppose we have a model for the Registration of a user to an application. The model goesas below:

public class RegistrationViewModel(){
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string TelNo { get; set; }
}

Thus in the view/UI user will be displayed with the above labels and respective text boxes for input. The razor engine view page in the application looks like:

@model ServerSideValidationDemo.Models.RegistrationViewModel
@{
 ViewBag.Title = "Registration Page";
}

@using (Html.BeginForm())
{

    • @Html.LabelFor(m => m.FirstName) @Html.TextBoxFor(m => m.FirstName, new { maxlength = 50 }) @Html.ValidationMessageFor(m => m.FirstName)
  • @Html.LabelFor(m => m.LastName) @Html.PasswordFor(m => m.LastName, new { maxlength = 50 }) @Html.ValidationMessageFor(m => m.LastName)

 

  • @Html.LabelFor(m => m.Address1) @Html.PasswordFor(m => m.Address1, new { maxlength = 50}) @Html.ValidationMessageFor(m => m.Address1)

 

  • @Html.LabelFor(m => m.Address2) @Html.TextAreaFor(m => m.Address2, new { maxlength = 200 }) @Html.ValidationMessageFor(m => m.Address2)

 

  • @Html.LabelFor(m => m.TelNo) @Html.TextBoxFor(m => m.MobileNo, new { maxlength = 10 }) @Html.ValidationMessageFor(m => m.MobileNo)

 

 

}

Thus, the above snippet would bring the user the UI where the users would post their input and click submit. In the razor view page, you can see the HTML Helper ValidationMessageFor. This helper displays the Validation message returned after validation from the server as response, at the respective model property. Like for example, we want the user to enter the Model property First name as mandatory, then after validation the helper would display the validation message beside the First Name Text Box.
Now lets have a look at the Action snippet to which the post would call after Submit click.

[HttpPost]
public ActionResult UserRegistration(RegistrationViewModel registerModel){
     if (string.IsNullOrEmpty(registerModel.FirstName))
         {
             ModelState.AddModelError("FirstName", "Please enter your first name");
         }
     if (!string.IsNullOrEmpty(registerModel.TelNo))
         { 
             Regex telNoRegex= new Regex("^9\d{9}$");
             if (!telNoRegex.IsMatch(registerModel.TelNo))
             ModelState.AddModelError("TelNo", "Please enter correct format of Telephone Number");
         }
     if(ModelState.IsValid){
         return View("Sucess");  //Returns user to success page
         }
      else {
         return View();  //Returns user to the same page back again
        }
 }

Before explaining the above snippet, lets understand how this will be called after Submit click.
@using (Html.BeginForm()), this does the trick even without specifying the Action and controller. This actually internally calls the Post method of the current url, i.e. looks for the HttpPost attribute to the respective action name of the current url. Thus, in this way the post method of UserRegistration gets called and this also post the required view model to the action, fetching the values input by the user.
After the Action Result method gets called, there is check for the properties explicitly. Here, we check if the user has input into the First name or not. If the user skipd the First Name textbox and submits, then we post the user with the validation message saying “Please enter the first name”. This validation check will not let the user post the input, unless he adds the first name. Similarly, the telephone number is also validated with the regular expression(for the indian telephone number) given.
This was all about the validation being done explicitly.
Now, since we are developing an MVC application, it provides pre defined attributes which can be used to validate our post data. The attributes are called Data-Annotations attribute. Lets look at their usages below:
The use of data annotations can be extensively done in order to avoid heavying the controller post action,explicitly checking for each property. The data annotations attribute in a view model would look like below:

public class RegistrationViewModel(){
    [Required]
    [Display(Name = "First name")]
    [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    [Required(ErrorMessage = "Please Enter Telephone Number")]
    [Display(Name = "Tele Phone")]
    [RegularExpression(""^9\d{9}$"", ErrorMessage = "Please Enter Correct format of Telephone No.")]
    public string TelNo { get; set; }
}

The view model above uses Data Annotations attributes and all the required validations for the properties are provided. Lets discuss one by one:

    1. Required:- This attribute forces the user to enter the value for that specific property and then submit the form, else diplays “The FirstName is required.”. Mark here, the previous message would be a default error message where as for the Tele phone number, the custom error message would be displayed.
    2. Display(Name = ):- This attribute sets the label for the model property. We just need to specify
      @Html.LabelFor(m=>m.TeleNo). This would display the specified custom label for the property, here it would display Tele Phone
    3. RegularExpression:- This attribute is very handy specially when we have properties like Email Address, Tele Phone Numbers and specific expressions for passwords in the forms. We just specify the expression in the attribute and it validates the input from user and states if it is valid or else displays the error message.

Thus, here the view page would go like the same as above. And when we submit, the action post method called would be different i.e. much less code. Lets have a look at the action below:-

[HttpPost]
 public ActionResult UserRegistration(RegistrationViewModel registerModel){
    if (ModelState.IsValid)
      {
         return View("Success");//Return to the success 
      }
    else
      {
         return View();//Return back to the same view 
      }
 }

Thus, the data annotations here made it so simple and easy.
Here then comes another security vulnerability, i.e. Cross-Site Request Forgery Attacks, which can be easily attacked using the simple Fiddler. When we post any data, we can easily manipulate the data posted by one user using the fiddler and damp into the application and even ruin it. This is indeed very dangerous. Lets see how to prevent Cross site forgery attacks

Preventing Cross Site forgery Attacks

In MVC applications, while posting the form data, it is quite simple to prevent such request if understood properly. MVC provides the attribute [ValidatAntiForgeryToken] on the respective action. Lets see the flow in the snippet first.
First we need to place the AntiForgeryToken helper in the razor view page like:

@using(Html.Form("UserRegistration", "Register")) { 
    @Html.AntiForgeryToken() 
    //Then here normal rest form as mentioned above    
 }

Then in the controller “Register” for the action “UserRegistration”(POST) add the attribute like below:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UserRegistration(RegistrationViewModel registerModel){
   //ModeState Valid check and rest code goes here
}

Ok, so we have seen what two simple steps we need to do. Now lets understand how it does. What happens exactly when we do not place these attributes. How vulnerable our controller is and to what extent an attacker can affect the application. Suppose we are on an Edit page, where a user soughts to edit few of his login information. Now an attacker from over a third party domain and host a simple HTML that would post some information to the same Edit action, the user were to. Then, some how the user if navigates to the Html page set up by the attacker, the user unknowingly is posting unwanted data to the server and normal saving to the database. Here the attacker may be replacing the email ids or any other vulnerable information to his own and retrieving the user’s data. BOOM! This is crash, rather a crap!
Thus, what we need to do here, we need to check if the request to the server action is coming from the same domain, the user has logged in ! for this we need to have some header or property which will be mapped when a request is made and if matches then post else let the authentication fail.
This is actually what the attribute does. The ValidateAntiForgeryToken actually sets a cookie to the incoming reuest called __RequestVerificationToken, and the same __RequestVerificationToken is set for the domain in which the user is logged in. Thus, when a request is made from the same domain, the request header cookie should match and let the user post the data, but when a request is made from the third party domain, then the request is rejected since the __RequestVerificationToken will never match, just failing the authentication and preventing the Cross Site Forgery by any attacker.
Now here there is another problem. If any how the attacker gets to know the Anti Forgery Token, then what!! again crap! No there is a way out here as well. The attribute has ability to add a unique/different Salt every time so that the same token is not reused everywhere.

@Html.AntiForgeryToken("SALT") //The salt can be any sort of string(homogeneous mixture :))

[ValidateAntiForgeryToken("SALT")]

Another concept that is vulnerable to such attacks and may breach the security in the application is SQL Injection Lets discuss this in brief. 🙂

SQL Injection Attacks & Prevention Techniques

What exactly is SQL Injection attack? thinkzoo
SQL Injection is an attack to fool and manipulate the application database. This is done through the malicious input from the user during post methods and if the posted data is not validated before being executed as sql query. This is really very dangerous which can let attackers get all the sensitive data or even delete the records from all tables, truncating them, just by posting a simple query to drop instead of actual data.
In this, the objective of the attacker is to post their query into the application and let the server run and give him the response if not handled in the server end. Lets see how:
Suppose we have a sql query to select the names of houses and display. The query would be like:

var sqlTobeExecuted = "SELECT HouseID, HouseName"+
    "FROM House " +
    "WHERE Address LIKE '" + searchInputParam +"%';
SqlDataAdapter da = new SqlDataAdapter(sqlTobeExecuted , DbCommand);

The above query is not parameterized and is a simple query in string format to get the house details. Now suppose the attacker posts the searchInputParam (which originally comes from the textbox input of the user) as

‘ UNION SELECT id,name FROM sysobjects;–

Mark the statement what becomes after that is passed to the string query,

SELECT HouseID,HouseName FROM House
WHERE Address LIKE ” UNION SELECT id,name FROM sysobjects;–%’

The first apostrophe in the searchInputParam closes the Like parameter in the SQL query and the double dashes “–” comment out the rest of the query. Thus that gives the list of all the HouseNames and also all the tables present in the database . Even they can also get the ids of the sysObjects and use the Ids to retrieve the column names of the database table they want. Suppose there is a table named Users. Oviously the table would have all the user details. Thus, with the id and the table name the attacker can retrieve the column names of the Users table using the below query:

‘ UNION SELECT name FROM syscolumns WHERE id = “USERID”;–

Thus,the whole of the database can be exposed to malicious users at a single click.
To prevent this,

      • Encrypt the essential and sensitive data like password, credit card info and other details. So that to some extent if by any how they get the details they cannot decrypt it. Use one way hashing to encrypt the record data.
      • Using parameterized queries instead of strings, in order to avoid directly injecting the values from the User input to the query as we saw in the above section. A parameterized query would prevent the malicious input and it would look like below:
        var commandToBeExecuted = "SELECT HouseID, HouseName FROM House"+
            "WHERE Address  Like @Address";
        SqlCommand cmd = new SqlCommand(commandToBeExecuted , conn);
        cmd.Parameters.Add("@Address",address);

        As we see in the above query we avoid passing directly the string input, instead we are using parameters into the SQL query, which would prevent such attacks.
      • use of parameterized Stored Procedures, which also prevent and prove to be a good solution to these mallicious attacks of injection. Also it is advisable to not trust them completely/blindly so it is always better to check for the sensitive data from user inputs and then execute the Stored procedure. This can be done, where the developer can think there are chances of vulnerability.
      • Entity Framework & LINQ, it is interesting to note here is while using LINQ to entity, the query generation does not use the string based approach, rather it uses the object model API, thus being not susceptible to SQL injection attacks.

Authentication & Authorization

These two are very very very…important in any application and these are two different concepts all together but are used to solve the same thing,i.e. Security. When we develop an secure application, the Login is highly essential. Thus, properly authenticating users to the application & authorizing users to particular section of the application is challenging. Usually Forms Authentication is implemented across MVC applications. In the web.config file, the following configuration is set:

Only this will not set the authentication. You need more set up be done. This would involve a lot of configuration. WebSecurity in MVC makes it easy and secure to be implemented. It provides tables and hashing as well. The hashing it provides is one way and very secure. You can learn more about implementing Web Security in MVC from
Web Security In MVC
Thus after setting this authentication, then the important thing is Authorization, which can be provided on controller level, action level, which can be customized in order to check for the access levels along with the sessions. Only Authorize attribute would let the check for the session, we can customized to check for the roles and access levels for the screens as well.

[Authorize]
 public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }

In the above snippet, the entire controller has been authorized. That is each method inside the controller will be first authorized.

public class HomeController : Controller
    {
      public ActionResult Index()
        {
            return View();
        }
       [Authorize]
       public ActionResult GetHome(){
         return View()
       }
    }

Here, only the action method GetHome is authorized, not the whole controller.
Thus, Authentication and Authorization are very important factors that ought to be taken into consideration.

More security considerations in MVC

Straight from the OWASP scurity points,
Its advisable to hide the MVC versions as well as Asp.Net versions we use, never expose the versions through the headers.

X-AspNet-Version 4.0.30319
X-AspNetMvc-Version 5.0

We need to hide the versions which appears in the Network tab of the developer table.
Lets know how to remove the versions of Asp.Net and Asp.Net Mvc from the headers.

    • Asp.net Version:-To hide the X version of the Asp.Net we use the below Web.Config change.

      The above will hide the Asp.net versions.
    • Asp.Net MVC Versions:- To hide the X version of the Asp.Net MVC we use the below change in the Application_Start method of the Global.asax. The snippet would go like below:-
      protected void Application_Start()
              {
                  MvcHandler.DisableMvcResponseHeader = true;

      This hides the Asp.Net MVC version from the headers in the Network tab.
    • Lastly, there are chances of exposing the Users to the Yellow screen of death, when an exception occurs in the application and is unhandled. Thus, it is advisable to have a custom error page, where users will be landing when exception occur. Lets see how:
      Custom errors in the Web config needs to be on. There are three modes of the Custom errors. They are:

      1. On:-
        –Prevents the stack trace that is shown when exceptions arise
        –Also allows to display custom error pages to the end user
        –Custom error pages shown to both Remote Clients as well as Local
      2. Off:-
        –Makes the end user view the description of the exception along with the entire stack trace.
        –ASP.NET error/exception and stack trace shown to both Remote clients and Local as well.
      3. Remote only:-
        –This is the best among all for the developers’ perspective, as this allows the Remote clients to view thecustom error messages/pages.
        –Allows the Local users/especially developers to view the ASP.NET errors.
        –This is the default value.

      The other attribute which is used to the custom error element is defaultredirect. This is used to redirect the users to a default page when exceptions occur.

      The exceptions can also be handled globally , application level by using the below snippet:

      protected void Application_Error(Object sender, EventArgs e)
      {
          Exception ex = Server.GetLastError();  //self explanatory gets the most recent error
          Server.ClearError();  //self explanatory clears the error 
              //(Required to clear as otherwise user gets to see the default ASP.NET error handlers)
          Response.Redirect(""); //default redirect. 
      }

      For details you can follow: Custom Errors

      Conclusion

      Thus, security and validations are very important features to be implemented in any application now a days. According to forbes in a day 30,000 sites were hacked. This is truly an astonishing numbers. And in today’s world most of the sensitive information are being stored on cloud. Thus, in any application the data have a great chance of being exposed and hacked. So security is a major concern and needs to be handled very carefully.
      Hopefully, Some of the major points are discussed above and can be implemented in any application to avoid any sort of breaching.

      References

      How can I miss the references from which I learnt and got this opportunity to share with the world.
      OWASP Cheat Sheet
      Security testing
      Sql Injection and Entity Framework

]]>
/validation-security-in-mvc-application/feed/ 0
Using Exception Filters in MVC applications /exceptionfilters-mvc/ /exceptionfilters-mvc/#respond Sun, 12 Jul 2015 16:27:30 +0000 /?p=396 Introduction

Exceptions, are like part and parcel of an application. They are boon and ban for an application to. Is’nt it?This would be controversial, for developers it helps them track minor and major defects in an application, and somtimes they are frustrating when it lets users land on the Yello screen of death each time. This would make the users mundane to the application. Thus to avoid this, developers handle the exceptions. But still sometimes there are a few unhandled exceptions. Now what is to be done for them? MVC provides us with built-in filters ‘Exception Filters’ about which we will discuss. Lets start..
exception cc: Google

Yellow screen of Death can be said as wadrobe malfuction of our application. 😀

Get Started

Exception filters run when some of the exceptions are unhandled and thrown from an invoked action. The reason for the exception can be anything and so is the source of the exception.

Creating an Exception Filter

Custom Exception Filters must implement the built in IExceptionFilter interface. The interface looks as :

public interface IExceptionFilter{
    void OnException(ExceptionContext filterContext)
}

Whenever an unhandled exception is encountered, the OnException method gets invoked. The parameter as we can see, ExceptionContext is derived from the ControllerContext and has a number of built in properties that can be used to get the information about the request causing the exception. There properties ExceptionContext possess are shown in the table:

Name Type Detail
Result ActionResult The result returned by the action being invoked.
Exception Exception The unhandled exceptions caused from the actions in the applications.
ExceptionHandled BOOL This is a very handy property, which returns a bool value (true/false) based on if the exception is handled by any of the filters in the applicaiton or not.

The exception being thrown from the action is detailed by the Exception property and once handled (if), then the property ExceptionHandled can be toggled, so that the other filters would know if the exception has been already handled and cancel the other filter requests to handle. The problem, lies that if the exceptions are not handled, then the default MVC behaviour shows the dreaded yellow screen of death, to the users, which puts up a very bad impact on the users and more importantly, it exposes the application’s handy and secure information to the outside world, which may have hackers and then the application gets into the road to hell. Thus, the exceptions need to be dealt very carefully.
Lets demonstrate one small custom exception filter.
This filter can be stored inside the Filters folder in the web project of the solution. Lets add a file/class called CustomExceptionFilter.cs

public class CustomExceptionFilter : FilterAttribute, IExceptionFilter {
     public void OnException(ExceptionContext filterContext) {
        if(!filterContext.ExceptionHandled &amp;&amp; filterContext.Exception is NullReferenceException) {
            filterContext.Result = new RedirectResult("customErrorPage.html");
            filterContext.ExceptionHandled = true;   
        }
    }
 }

Now let us understand what this actually does. as we can see this implements the interface as mentioned earlier and thus implements the method, OnException. This mehtod has the parameter ExceptionContext, the properties of which is mentioned in the table. In this custom filter we have handled the most common and neglected exception “Null Reference Exception”, arises when a value returning null is not handled/checked and used in further implementations. The custom filter derives the FilterAttribute as to be used as Attribute over the action or the controller directly like [CustomExceptionFilter]. In this implementation above, we have used almost allthe important properties of the ExceptionContext. First, the check is used for the ExceptionHandled which returns a boolean value if the exception has been handled or not. If not then Check for the type of exception arisen. Since here we have used the NullReferenceException, we check for that exception. Then if the conditions are satisfied/passed we manipulate the result and return the RedirectResult (ActionResult type) and let the users land on a custom error page created in the application, to avoid the yellow dreaded screen.

The use of the filter is pretty simple as this custom filter extends from the FilterAttribute. So based on the usage, this can be used as [CustomExceptionFilter] on the Controller Levelor the individual Action level,which ever is mandate.

//Over controller
 [CustomExceptionFilter]
 public class HomeController:Controller {
    //......
 }
//Over the Action
 [CustomExceptionFilter]
 public ActionResult Index() {
    //.......
 }

Now, lets discuss about the in built HandleAttribute. This is a built in class which is used similar way as a filter attribute in MVC applications. The most important thing is this attribute works only when the custom errors in the web.config is enabledor set to true.

the default mode for this element is RemoteOnly, which willonly work out when application is deployed and request is made from some other systems.
Lets look at the properties of the HandleError Attribute.

  • ExceptionType: This property, as the name suggests tells the attribute the type of exception it needs to handle.
  • View: This is the property, which we need to specify inorder to lets the attribute, land the end users after handling the exception
  • Master: If there is a special layout, we have for the error page, then this master can be set to that layout path, if left empty, this will take the default layout of the application for the error pages.

Thus, the below code snippet shows how to use the HandleError attribute

[HandleError(ExceptionType = typeof(NullReferenceException), View = "CustomErrorPage")] {
public Action Result {
    //........
    var testVal = null;
    //Unhandled and used..
 }

Caution: While reading through the Adam Freeman, a very interesting note of caution was mentioned while using the HandleError attribute. In the custom error page, we would be using the HandleError Info like the Stack Trace, the exception message etc. Since we would not like to show this to the end user, we need to put the stack trace inside a hidden field or make the html tag invisible because The view is not displayed tothe user unless the Exception.StackTrace is included in the View..

Conclusion & References

Thus, we learnt the creation of custom exception filters as well as the built-in filters in MVC applications.There are various ways/tools now tohandle exceptions, but stillwe can make use of these filters in order to avoid detrimental effects on our applications.
References: Adam Freeman-Professional Asp.Net MVC 4 & MSDN
I hope this would help developers & beginners. The concept is interesting when we use them. So start using and enjoy Coding. 🙂

]]>
/exceptionfilters-mvc/feed/ 0
Using Rotativa in MVC application /using-rotativa-in-mvc-application/ /using-rotativa-in-mvc-application/#comments Thu, 02 Jul 2015 17:21:13 +0000 /?p=371 Introduction

Generating PDF from your web applications is easy, simple and reliable. There are many tools/packages available in the Nuget. Here, in this article we would learn how to use Rotativa in the MVC applications. Rotativa makes it very easy to generate pdf from an HTML. It is actually derived version of wkhtmltopdf which converts html to pdf. The browsers as they use the webkit engine to render the HTML. According to wiki, WebKit is a layout engine software component for rendering webpages in web browsers. Making custom changes to the pdf document generated is quite simple too. Using this we can directly download the pdf document for the user or else we can also prompt the document inside an i-frame. Lets see how to implement this wonderful tool.

Implementation

Ofcourse, we need to install the package before starting the implementation. To install the package from the package manager console, the command goes like:

Install-Package Rotativa

Then, we can find the rotativa reference under the reference, with a separate folder named ‘Rotativa’ with the following contents.
Another folder named App_Browsers which has the contents required by the package Rotativa.
Rotativa1

 

Now we are ready to implement the Rotativa using the codes we will discuss below to generate pdf to directly download it as well as show it in another window. Thus, lets have a look.
To implement the pdf using rotativa, we just need to specify the codes below in a separate action method.

public ActionResult Test()
        {
            var students = new List<xx>
            {
                new xx() {action = "ABC", email = "[email protected]", firstName = "test", lastName = "test"},
                new xx() {action = "ABC", email = "[email protected]", firstName = "test", lastName = "test"},
                new xx() {action = "ABC", email = "[email protected]", firstName = "test", lastName = "test"},
                new xx() {action = "ABC", email = "[email protected]", firstName = "test", lastName = "test"}
            };

            return new Rotativa.ViewAsPdf("TestView", students);
        }

The above code is a simple action method, where we have created a new model and then as we can see, the return statement here, new Rotativa.ViewAsPdf(“TestView”,students). This states that a new rotativa type is created which is used to view the pdf. To this method as you can see, we have passed the first parameter as the View Name and the second parameter as the View Model set for the view. Only the view name can also be used/passed to the overloaded parameter of that method.

  • ViewAsPdf:- This method just displays the view as pdf in the same window and to display the same pdf in another window, we can manipulate in the javascript as
    window.open(url)
  • ViewAsPdf-To Download:-This is not property method of the Rotativa class, but can be used differently to download directly the pdf file. Lets see the code below:
    public ActionResult Test()
            {
               
                var pdfResult = new ViewAsPdf("TestView")
                {
                    FileName = "ExamReport.pdf",
                    CustomSwitches =
                        "--footer-center \"Name: " + "XYZ" + "  DOS: " +
                        DateTime.Now.Date.ToString("MM/dd/yyyy") + "  Page: [page]/[toPage]\"" +
                        " --footer-line --footer-font-size \"9\" --footer-spacing 6 --footer-font-name \"calibri light\""
                };
    
               return pdfResult;
                
            }

    Just user to declare a new type as ViewAsPdf and just return to the action. This will directly download the file for you.
  • ActionAsPdf:- This would return the specified action which returns a view with a viewmodel as pdf. The code would go as below:

    public ActionResult Test(int testID)
    {
         var students = new List<xx>
                {
                    new xx() {action = "ABC", email = "[email protected]", firstName = "test", lastName = "test"},
                    new xx() {action = "ABC", email = "[email protected]", firstName = "test", lastName = "test"},
                    new xx() {action = "ABC", email = "[email protected]", firstName = "test", lastName = "test"},
                    new xx() {action = "ABC", email = "[email protected]", firstName = "test", lastName = "test"}
                };
        // code to retrieve data from a database
        return View(students);
    }

These are the common methods being used usually.
Now, There is another beautiful thing to mark here. The customization which can be done to the pdf files. The use of Custom Switches.

var pdfResult = new ViewAsPdf("TestView")
            {
                FileName = "ExamReport.pdf",
                CustomSwitches =
                    "--footer-center \"Name: " + "XYZ" + "  DOS: " +
                    DateTime.Now.Date.ToString("MM/dd/yyyy") + "  Page: [page]/[toPage]\"" +
                    " --footer-line --footer-font-size \"9\" --footer-spacing 6 --footer-font-name \"calibri light\""
            };

The FileName property is used to set the file name for the pdf being downloaded. The Custom Switches is the best property. As we can mark the structure is bit messy, but is not cumbersome. Based on the wkhtmltopdf there are a list of options which can be used to customize the PDF file. Here in the above code snippet, we have a footer customized.

  • –footer-center:- This aligns the footer at the center foot of the page.
  • Page:[page]/[toPage]:- The [page] to [toPage] marks the current page and the total number of pages in the file.
  • –footer-line:-Displays line above the footer
  • –footer-font-size:-Sets the font size of the footer elements
  • –footer-spacing:-Sets the spacing between the footer-line and the text
  • –footer-font-name:-Sets the font family/style of text

For more options and details please visit the url –wkhtmltopdf

Conclusion & References

Thus, we saw how easy it is to implement the Rotativa in MVC applications and generate a pdf in minutes. Implement and enjoy

References:

wkhtmltopdf

Nuget Rotativa

Github Rotativa

]]>
/using-rotativa-in-mvc-application/feed/ 1
Understanding Filters in MVC /understanding-filters-in-mvc/ /understanding-filters-in-mvc/#respond Sun, 08 Mar 2015 10:18:59 +0000 /?p=308 Introduction

There are scenarios when we have an implementation which will be reused at many places, which is not confined to a single place or method. This is fulfilled by the Filters in MVC. This is a very good concept introduced in MVC. The implementation which is mentioned above is called cross-cutting concerns. Thus, in simple terms, this add an extra logic to be implemented into the request being processed. Some of the examples of cross cutting conerns are Authorization & Output Caching. Lets discuss the different types of filters and how to create them and use them.

Getting started

Lets see first a glimpse of how the filters are used:-

namespace WebSecurityDemoTest.Filters
{
    public class WebSecurityAuthorize:AuthorizeAttribute
    {
        protected bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (!httpContext.Request.IsAuthenticated)
            {
                return false;
            }
            if (HttpContext.Current.Session["SessionHelper"] == null)
            {
                return false;
            }

            return true;
        }

        protected void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.Result = new RedirectResult("/");
            base.HandleUnauthorizedRequest(filterContext);
        }

    }
}

The above snippet is an example of an CustomAuthorize attribute. This attribute is a kind of Filter only. As this is defined here once and is used as an MVC attribute at many places as this needs to be checked at every controller level in every application where athorization is a must. Now lets see if this would not have been the case, how explicitly we would have checked at every action level.

namespace WebDemo.Controllers{
    public class DemoController : Controller {
        //..instances or constructor if any read onlyvariables used
        public ActionResult Index() {
         if(!Request.IsAuthenticated) {
           FormsAuthenticationn.RedirectToLoginPage();//MVC WebSecurity
          }
         //else rest implementation..
         }
     }
}

In the above snippet as you can see the Request.IsAuthenticated is checked at each action level, as the authentication needs to be checked before letting the anonymous user access the action. Thus is redundancy can be normalized by the use of Filters.

By just using [Authorize] or [CustomAuthorize] at the controller/action level. Thus we can say Filters are attributes that help in adding an extra check at the routing level. As this needs to be checked during the request processing only. Attributes are special classes which get derived from the namespace System.Attribute. 

Basically there are four types of filters that the MVC framework support. They are:

Filter Type Inheritance What this does
Authorization IAuthorizationFilter Runs first during the request processing before any other filters or the action execution
Action IActionFilter Runs before the action execution(Action level)
Result IResultFilter Runs before after the action execution(Action level)
Exception IExceptionFilter Runs only when any action method or any other filter throw exception

Before the invokation of any action method, the framework first looks for any definition of any filter attributes, then moves into the action method execution, which in turn gives an extra level of security to the application without writing redundant codes.
Lets look into each briefly.

Authorization Filter

This as the name suggests is required to provide authoization level in the application. The default attribute is [Authorize]. Its constructor also can accept parameters like Roles [Authorize(Roles=”Admin”)] which is very handy as the roles based application are very common now a days.
Authorization filters as mentioned in the table above runs the first before any filter’s execution or even before the action methos execution.
The below snippet shows how the Interface from which it extends looks like:

namespace System.Web.MVC {
    public interface IAuthorizationFilter {
        void OnAuthorization(AuthorizationContext filterCOntext);
    }
}

The best thing is we can customize the Authorize attribute by extending our custom authorize class from the Authorize attribute class and manipulate our logic there, which I have mentioned in the very first snippet. A nice tip here is to keep the Custom Authorize attribute very simple.

Built in Authorize attribute also accept the Users parameter like [Authorize(Users=”Suraj”,”Simon”,”Mike”)], which filters the action based on the users access level.

The use is also very simple. Either we can use at the controller level or the action level. Just place [CustomAuthorize]  before the controller class or the action methods.

Action Filter

The action filter can be used for any purpose, why any as the Interface it extends supports two methods to be invoked. Asmentioned in the table, this filter may be executed before the Action execution but not the first. Lets look at the Interface

namespace System.Web.MVC {
    public interface IActionFilter {
       void OnActionExecuting(ActionExecutingContext filterContext);
       void OnActionExecuted(ActionExecutedContext filterContext);
    }
}

As you can see in the above snippet, the interface has two methods to be defined, as the method names suggest, the first one OnActionExecuting tells us that before the action method has been invoked we can use this method, similarly the second one says that once the action method gets executed then this can be invoked. Now lets see each of them one by one .

actionFilter

OnActionExecuting Method

As we have already discussed this method is invoked before the action starts getting executed.The filterContext of type ActionExecutingContext passed as the parameter contains the following properties:

Name Description
ActionDescriptor This provides the details of an action method
Result This gives the result for the action method, the filter can be manipulated to cancel the request also

Lets look into the implementation of this method, in a custom action filter attribute:

namespace Filters.WebDemoInfra {
    public CustomActionFilter : FilterAttribute , IActionFilter {
       public void OnActionExecuting(ActionExecutingContext filterContext)
         if(filterContext.HttpContext.Request.IsLocal) {
              filterContext.Result = new HttpNotFoundResult();
          }
       }

Thus when we try and understand what we have written in the snippet above, we find that, whe before the action gets executed, this method gets invoked, the method OnActionExecuting returns a not null result i.e. HttpNotFoundResult, which will land the user on a 404 not found error page, even if the action has a view defined. This is the power of this filter.

Now lets look into it’s sister’s implementation.

OnActionExecuted

This method as defined ago, can be invoked to span the execution of the action method being processed based on the request. Lets check with the help of an example which will measure the time taken for the action to complete the full execution.

namespace Filters.WebDemoInfra {
    public class CustomActionFilter : FilterAttribute , IActionFilter {
      private StopWatch watch; //System.Diagnostics
      
      public void OnActionExecuting(ActionExecutingContext filterContext) {
         timer = Stopwatch.StartNew();
       }

      public void OnAcionExecuted(ActionExecutedContext filterContext) {
       timer.Stop();
       if(filterContext.Exception == null) {
         filterContext.HttpContext.Response.Write(string.Format("Total Tme taken: {0}", timer.Elapsed.TotalSeconds));
       }
    }
  }
}

The above snippet is a very simple sippet to understand. The private variable is of type StopWatch which is an in-built class in the namespace System.Diagnostics. In the executing method, we are initializing the timer and after execution of the action method since the executed method gets invoked, so to the httpContext which contains both Request and response as well, we assign the time elapsed in seconds to the Response.

Lets look at the properties provided by the OnActionExecuted method.

Name Description
ActionDescriptor This provides the details of an action method
Cancelled If incase the action has been cancelled by any other filter this property returns true
Exception If any filter or any action throws an exception, it is returned by this property
ExceptionHandled If any filter or any action throws an exception and it has been handeled, this property returns true
Result This gives the result for the action method, the filter can be manipulated to cancel the request also

Thus, this was all about the Action filters.

Result Filter

These are quite similar to the Action Filters. These are the filters which are invoked or operate on the results being produced by the Action Result methods. This implements from the IResultFiler interface which also looks quite similar to the IActionFilter. Lets see how:

namespace System.Web.MVC {
    public interface IResultFilter {
       void OnResultExecuting(ResultExecutingContext filterContext);
       void OnResultExecuted(ResultExecutedContext filterContext);
    }
}

OnResultExecuting

OnResultExecuting method gets invoked when result has been returned by the Action method but before the the action is executed fully. This also has the same properties as the OnActionExecuting method as described in the table.

OnResultExecuted

OnResultExecuted method gets invoked after the action result has been executed. Here also the parameter filterContext contains the same properties as the OnActionExecuted method has described in the table above. The demostration
can be the same Timer as described in the Action filter section.
Below snippet will show you the built-in Action and Result Filter class.

public Abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter {
  public virtual void OnActionExecuting(ActionExecutingContext filterContext){
     }

public virtual void OnActionExecuted(ActionExecutedContext filterContext){
     }

public virtual void OnResultExecuting(ResultExecutingContext filterContext){
     }

public virtual void OnResultExecuted(ActionExecutedContext filterContext){
     }
   }
}

Using Global Filters

This is a very nice feature that can be implemented in the MVC application. Global.asax as we all know is the heart of the MVC web application. The Application_Start method is called from here whenever the application starts. We have a FilterConfig.cs file inside our App_start folder, where we can find a static method called RegisterGlobalFilters. In this method we register our custom filter which needs to be invoked through out the application which is applied to all controllers and actions in the application. Lets see how we register:

namespace Filters { 
    public class FilterConfig {
        public static void RegisterGlobalFilters(GLobalFilterCollection filters) {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new CustomAllAttribute());
        }
    }
}

Thus the second filter added/registered as the global filter is our custom attribute. This custom attribute implementation needs to be thought upon and then written as this would be used through out the application, so this should also be very simpleso that can be manipulated and maintained at any point of time.

Filter Ordering

In MVC framework, the order in which the filter get invoked (if there are more than one at the action), doesnot matter much. But even if you wish to add ordering based on the business logic we have, then we can use the Order keyword which accept an int value to set the order of the Filter invokation/execution. Lets take an example and understand

[ProfileA(Message = "First")]
[ProfileB(Message = "Second")]
public ActionResult Index() {
   //Implementation
 }

In the above snippet we have two custom filters ProfileA and ProfileB that take message as parameter and print that using the context response write method. Thus, this would write

“First” (For OnActionExecuting)

“Second”  (For OnActionExecuting)

“Second”  (For OnActionExecuted)

“First”  (For OnActionExecuted)

Thus if we wish to modify the order like the “Second” would come first then the “First”, then we need the use of Order.

[ProfileA(Message = "First"), Order=2]
[ProfileB(Message = "Second"), Order=1]
public ActionResult Index() {
   //Implementation
 }

Thus, here the output as previous will change based on the order specified in the above snippet. Thus based on the requirement we can specify as many filters may it be built-in or custom and set the order of execution also. This is how flexible MVC framework is. 🙂

Conclusion

Thus here I tried to explain the Filters that are being used in MVC framework. Here I have discussed Authorize, Action & Result filters. I will try and explain the Exception filter in the next section.
Thanks for your patience.
Corrections and suggestions are humbly accepted. 🙂

References

  • Adam Freeman- Pro ASP.NET MVC
]]>
/understanding-filters-in-mvc/feed/ 0
Upload .csv file in MVC application using ajax /upload-csv-file-in-mvc-application-using-ajax/ /upload-csv-file-in-mvc-application-using-ajax/#respond Fri, 06 Mar 2015 19:45:57 +0000 /?p=303 Introduction

CSV(Comma Separated Values), which means the values are separated by commas. Usually in applications, there is a requirement to upload .csv files only through the HTML uploader and retrieve the values and save to the database. Lets explore how and understand each step.
Below image shows how a .csv file looks like:-

csvFormat

 

The first row in the document image depicts the column headers. The below rows are the  values for the headers which we will be retrieving and saving into the database. Remember we will also need to delete the first and the last rows as they would not be saved into the database, infact they cannot be. 😀

Get started

To start with this we need to have a sample .csv file to test. I would be using the sample as mentioned in the image. First of all we need to create a view model for holding the values while looping through the file data. Lets have a look how our viewmodel would look like:

public class CsvRecordsViewModel
{
    public string Name{get;set;}
    public string School{get;set;}
    public int Age{get;set;}
    public string DOB{get;set;}
    public string ParentName{get;set;}
}

This is the view model which will hold the values for each row in the .csv file which we will be retrieving running through a loop.
But before that we need to fetch the file and then send to the server for processing. We will be doing this through Ajax:

$("#submitBox").click(function () {
    var fileUpload = document.getElementById("IDofTheUploader");
    if (fileUpload .value != null) {
        var uploadFile = new FormData();
        var files = $("#IDofTheUploader").get(0).files;
        // Add the uploaded file content to the form data collection
        if (files.length > 0) {
            uploadFile.append("CsvDoc", files[0]);
            $.ajax({
                url: "/Controller/Action",
                contentType: false,
                processData: false,
                data: uploadFile,
                type: 'POST',
                success: function () {
                   alert("Successfully Added & processed");
                }
            });
        }
    }
});

Lets understand what happens inside the snippet mentioned above. When the user selects a file from the browse window, he needs to select a .csv file nothing other than that. For that we need to give a check both at the client level and the server level. Below snippet shows how to restrict the user from uploading some other extension file:

$("#IDofTheUploader").change(function () {
        var selectedText = $("#IDofTheUploader").val();
        var extension = selectedText.split('.');
        if (extension[1] != "csv") {
            $("#IdofTheTextBoxUpload").focus();
            alert("Please choose a .csv file");
            return;
        }
        $("#IdofTheTextBoxUpload").val(selectedText);

    });

Thus, if a user tries to upload some other extension file, he gets an alert saying Please choose a .csv file. As you can see we have checked based on the upload Id input change function and the last line, if the file extension matches .csv then add the file path text into the text box. Then after that when the user hits/clicks Submit, then the “.click” function works out. At first we get the fileUploadId, then we check if the fileUpload value is not null. It automatically treats it as file as it includes already the input HTML element of type File. Then we declare a variable of type FormData, which will contain the entire file and the details. Then we get the files using the fileUploadId. If the files exist which we check from the length, then the file is appended into the FormData type variable declared earlier, then we make the ajax call to the server. Just keep in mind to add the ProcessData and the contentType to be passed in the ajax call. We send the data as the same name as uploadFile(of type FormData()).

After this the file is sent to the server where we read though the file using the InputStream. Lets first have a look at the snippet:

/// <summary>
        ///  Controller method to validate the csv document before upload
        /// </summary>
        /// <returns></returns>
        public ActionResult UploadCsvFile()
        {
            var attachedFile = System.Web.HttpContext.Current.Request.Files["CsvDoc"];
            if (attachedFile == null || attachedFile.ContentLength <= 0) return Json(null);
            var csvReader = new StreamReader(attachedFile.InputStream);
            var uploadModelList = new List<CsvRecordsViewModel>();
            string inputDataRead;
            var values = new List<string>();
            while ((inputDataRead = csvReader.ReadLine()) != null)
            {
                    values.Add(inputDataRead.Trim().Replace(" ", "").Replace(",", " "));
              
            }
            values.Remove(values[0]);
            values.Remove(values[values.Count - 1]);
	    using(var context = new Entities()){
            foreach (var value in values)
            {
                var uploadModelRecord = new CsvRecordsViewModel();
                var eachValue = value.Split(' ');
                uploadModelRecord.Name = eachValue[0]!=""?eachValue[0]:string.Empty;
                uploadModelRecord.School = eachValue[1] != "" ? eachValue[1] : string.Empty;
                uploadModelRecord.Age = eachValue[2] != "" ? eachValue[2] : string.Empty;
                uploadModelRecord.DOB = eachValue[3] != "" ? eachValue[3] : string.Empty;
                uploadModelRecord.ParentName = eachValue[4] != "" ? eachValue[4]:string.Empty;
                uploadModelList.Add(newModel);// newModel needs to be an object of type ContextTables.
				context.TableContext.Add(uploadModelRecord);
	      }
			context.SaveChanges();
	  }
            return Json(null);
        }

The above is the action method where the server side operation runs. Pardon me for using context object inside the controller, this is just for the demo, please “Do Not Add context in controller”.  Now look at the above snippet for the attachedFile, this now contains the file which we had sent as data from ajax call and accessed through, Current request in the context using the same name as the FormData() variable append Name. Then we create a new object for the Csv Reader which is of type StreamReader() which takes the attachedFile’s InputStream as parameter. Then we declare a string variable which will have the each row or line read from the csv file using the csvReader object ReadLine() property. If that is not null, then we manipulate the string row and then add each row now to a list of string type object. We replace the spaces with empty and the comma with spaces so that it will be easy to split and start extracting the values.

Then the most important task is to remove the first and last row in the .csv file which have been retrieved and saved into the vaues object.  Thus we remove the 0th element and the Count – 1 value(row) and then we work on our creation of the viewModel and then save into the database table.

Conclusion

This is a very simple and handy code snippet article which may come into work at any moment of the application. There are a lot of records which can be retrieved and manipulated using this snippet and either mail or create a viewmodel and save as we did above. Thus when we hear it may seem hard and complex but it is that simple, as without saving/uploading the file into the File System we are directly readig the file at runtime. I hope this becomes handy for all.
I am not an expert, so suggestions and corrections are humbly welcome.
Thanks for your patience.

]]>
/upload-csv-file-in-mvc-application-using-ajax/feed/ 0