Showing posts with label MVC. Show all posts
Showing posts with label MVC. Show all posts

Sunday, June 24, 2018

How we can call a JavaScript function on the change of a Dropdown List in MVC?

Create a JavaScript method:
Invoke the method:
<%:Html.DropDownListFor(x => x.SelectedProduct, new SelectList(Model.Customers, “Value”, “Text”), “Please Select a Customer”, new { id = “ddlCustomers”, onchange=” DrpIndexChanged ()” })%>

10:48 PM by Dilip kakadiya · 0

How to change the action name in MVC?

“ActionName” attribute can be used for changing the action name. Below is the sample code snippet to demonstrate more –
[ActionName(“TestActionNew”)]
public ActionResult TestAction()
{
return View();
}
So in the above code snippet “TestAction” is the original action name and in “ActionName” attribute, name — “TestActionNew” is given. So the caller of this action method will use the name “TestActionNew” to call this action.

10:47 PM by Dilip kakadiya · 0

How to enable Attribute Routing?

Just add the method — “MapMvcAttributeRoutes()” to enable attribute routing as shown below
public static void RegistearRoutes(RouteCollection routes)
{
routes.IgnoareRoute(“{resource}.axd/{*pathInfo}”);
//enabling attribute routing
routes.MapMvcAttributeRoutes();
//convention-based routing
routes.MapRoute
(
name: “Default”,
url: “{controller}/{action}/{id}”,
defaults: new { controller = “Customer”, action = “GetCustomerList”, id = UrlParameter.Optional }
);
}

10:45 PM by Dilip kakadiya · 0

Tuesday, November 15, 2011

file upload with Preview in ASP.NET MVC

  Introduction :

        Previewing an image is a great way to improve the UI of your site. Also it is always best to check the file type, size and see a preview before submitting the whole form. There are some ways to do this using simple JavaScript but not work in all browsers (like FF3).In this Article I will show you how do this using ASP.NET MVC application. You also see how this will work in case of nested form.
  Description :

         Create a new ASP.NET MVC project and then add a file upload and image control into your View.
<form id="form1" method="post" action="NerdDinner/ImagePreview/AjaxSubmit">
            <table>
                <tr>
                    <td>
                        <input type="file" name="imageLoad1" id="imageLoad1"  onchange="ChangeImage(this,'#imgThumbnail')" />
                    </td>
                </tr>
                <tr>
                    <td align="center">
                        <img src="images/TempImage.gif" mce_src="images/TempImage.gif" id="imgThumbnail" height="200px" width="200px">
                    </td>
                </tr>
            </table>
        </form>
 
         Note that here NerdDinner is refers to the virtual directory name, ImagePreview is the Controller and ImageLoad is the action name which you will see shortly
         I will use the most popular jQuery form plug-in, that turns a form into an AJAX form with very little code. Therefore you must get these from Jquery site and then add these files into your page.
 
        <script src="NerdDinner/Scripts/jquery-1.3.2.js" mce_src="NerdDinner/Scripts/jquery-1.3.2.js" type="text/javascript"></script>
        <script src="NerdDinner/Scripts/jquery.form.js" mce_src="NerdDinner/Scripts/jquery.form.js" type="text/javascript"></script>
 
          Then add the javascript function. 
<script type="text/javascript">
function ChangeImage(fileId,imageId){
$("#form1").ajaxSubmit({success: function(responseText){
var d=new Date();
$(imageId)[0].src="NerdDinner/ImagePreview/ImageLoad?a=" mce_src="NerdDinner/ImagePreview/ImageLoad?a="+d.getTime();
}
});
}
</script>

          This function simply submit the form named form1 asynchronously to ImagePreviewController's method AjaxSubmit and after successfully receiving the response, it will set the image src property to the action method ImageLoad. Here I am also adding querystring, preventing the browser to serve the cached image.
          Now I will create a new Controller named ImagePreviewController.
 public class ImagePreviewController : Controller
{
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AjaxSubmit(int? id)
{
Session["ContentLength"] = Request.Files[0].ContentLength;
Session["ContentType"] = Request.Files[0].ContentType;
byte[] b = new byte[Request.Files[0].ContentLength];
Request.Files[0].InputStream.Read(b, 0, Request.Files[0].ContentLength);
Session["ContentStream"] = b;
return Content( Request.Files[0].ContentType+";"+ Request.Files[0].ContentLength );
}
public ActionResult ImageLoad(int? id)
{
byte[] b = (byte[])Session["ContentStream"];
int length = (int)Session["ContentLength"];
string type = (string)Session["ContentType"];
Response.Buffer = true;
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = type;
Response.BinaryWrite(b);
Response.Flush();
Session["ContentLength"] = null;
Session["ContentType"] = null;
Session["ContentStream"] = null;
Response.End();
return Content("");
}
}

          The AjaxSubmit action method will save the image in Session and return content type and content length in response. ImageLoad action method will return the contents of image in response.Then clear these Sessions.
          Just run your application and see the effect.

Checking Size and Content Type of File:

         You may notice that AjaxSubmit action method is returning both content type and content length. You can check both properties before submitting your complete form.

  $(myform).ajaxSubmit({success: function(responseText)
            {               
                var contentType=responseText.substring(0,responseText.indexOf(';'));
                var contentLength=responseText.substring(responseText.indexOf(';')+1);
                // Here you can do your validation
                var d=new Date();
                $(imageId)[0].src=" /NerdDinner/ImagePreview/ImageLoad?a="+d.getTime();
            }
        });

Handling Nested Form Case:

         The above code will work if you have only one form. But this is not the case always.You may have a form control which wraps all the controls and you do not want to submit the whole form, just for getting a preview effect.
          In this case you need to create a dynamic form control using JavaScript, and then add file upload control to this form and submit the form asynchronously
function ChangeImage(fileId,imageId) {
var myform=document.createElement("form");
myform.style.display="none";
myform.action="/ImagePreview/AjaxSubmit";
myform.enctype="multipart/form-data";
myform.method="post";
var imageLoad;
var imageLoadParent;
var is_chrome = /chrome/.test( navigator.userAgent.toLowerCase() );
if(is_chrome && document.getElementById(fileId).value=='')
return;//Chrome bug onchange cancel
if(document.all || is_chrome){//IE
imageLoad=document.getElementById(fileId);
imageLoadParent=document.getElementById(fileId).parentNode;
myform.appendChild(imageLoad);
document.body.appendChild(myform);
}
else{//FF
imageLoad=document.getElementById(fileId).cloneNode(true);
myform.appendChild(imageLoad);
document.body.appendChild(myform);
}
$(myform).ajaxSubmit({success:
function(responseText){
var d=new Date();
$(imageId)[0].src="http://weblogs.asp.net/ImagePreview/ImageLoad?a=" mce_src="http://weblogs.asp.net/ImagePreview/ImageLoad?a="+d.getMilliseconds();
if(document.all || is_chrome)//IE
imageLoadParent.appendChild(myform.firstChild);
else//FF
document.body.removeChild(myform);
}
});
}

         You also need append the child in order to send request and remove them after receiving response. 

4:50 AM by Dilip kakadiya · 0

Thursday, November 10, 2011

Building A Color Picker Using ASP.NET MVC And jQuery


If you've used Microsoft's Ajax Control Toolkit, you'll probably have used a control called the ColorPicker. This is where it displays a list of colors that you can select from in a web page, and have the hex value of that color displayed when you click on it. I thought it would be a good exercise to show you how to do this using ASP.NET MVC and jQuery. Well here's how to do it. The example I’m demonstrating in this article is using the new jQuery 1.4 Alpha 2 release.  The end result will look like the screen cast below. If you cannot view the screencast shown below for some reason, you can directly view the screencast over here







To demonstrate this I’ve created an ASP.NET MVC application. For this example to work I obviously need some colors to display on the web page. Instead of hard coding a list of HTML hex values, the alternative approach is to retrieve the values from a source. The source for this example will be a list of known system colors in Windows. Let's start by creating a Colors controller that will return a HTML table with all the colors. Here's the code to do this:
C#
public class ColorController : Controller
{
      [AcceptVerbs(HttpVerbs.Get)]
      public JsonResult FetchColors()
      {
            var count = 0;
            var sb = new StringBuilder();
            sb.Append("<table><tbody><tr>");
           
            foreach (var color in Enum.GetNames(typeof(KnownColor)))
            {
                var colorValue = ColorTranslator.FromHtml(color);
                var html = string.Format("#{0:X2}{1:X2}{2:X2}",
                                    colorValue.R, colorValue.G, colorValue.B);
                sb.AppendFormat("<td bgcolor=\"{0}\">&nbsp;</td>", html);
                if (count < 20)
                {
                    count++;
                }
                else
                {
                    sb.Append("</tr><tr>");
                    count = 0;
                }
            }
            sb.Append("</tbody></table>");
            return Json(sb.ToString());
      }
}
VB.NET (Conversion Tool)
Public Class ColorController
      Inherits Controller
      <AcceptVerbs(HttpVerbs.Get)> _
      Public Function FetchColors() As JsonResult
             Dim count = 0
                  Dim sb = New StringBuilder()
                  sb.Append("<table><tbody><tr>")
 
                  For Each color In System.Enum.GetNames(GetType(KnownColor))
                        Dim colorValue = ColorTranslator.FromHtml(color)
                        Dim html = String.Format("#{0:X2}{1:X2}{2:X2}", colorValue.R, colorValue.G, colorValue.B)
                        sb.AppendFormat("<td bgcolor=""{0}"">&nbsp;</td>", html)
                        If count < 20 Then
                              count += 1
                        Else
                              sb.Append("</tr><tr>")
                              count = 0
                        End If
                  Next color
                  sb.Append("</tbody></table>")
                  Return Json(sb.ToString())
      End Function
End Class
I've decorated the action to only accept HTTP GET requests from the website by using the AcceptVerbs attribute. 
[AcceptVerbs(HttpVerbs.Get)]
It's important to explicitly state what request an action will accept. This way if a malicious user tries to post data to this action, the request will be ignored by the action. To get the collection of colors from the system I enumerate through the Enum.GetNames method by specifying the type as KnownColors. From there I retrieve the HTML hex value from the following two lines of code:
var colorValue = ColorTranslator.FromHtml(color);
var html = string.Format("#{0:X2}{1:X2}{2:X2}",
      colorValue.R, colorValue.G, colorValue.B);
 
I've also keeping track of how many <td> cells I create per row. Once the count reaches 20, I start a new <tr> row. If I didn't do this then the colors would print out entirely in the first <tr>. Doesn't look too appealing! Finally the generated HTML is returned as a JSON object.
 
All the server side code is finished now. The code below is for the view to render the color picker. I'll explain what I'm doing afterwards:
 
<script language="javascript" type="text/javascript" src="http://code.jquery.com/jquery-1.4a2.js"></script>
<script language="javascript" type="text/javascript">
        $(function() {
            $("#Colors").hide();
            $("#SelectColor").click(function() {
                $.get("/Color/FetchColors"nullfunction(data) {
                    $("#Colors").html(eval(data));
                });
                $("#Colors").toggle();
            });
 
            $("td").live("mouseover", (function() {
                $("#Sample").css("background-color", $(this).css("background-color"));
                $(this).css("cursor""pointer");
            }));
 
            $("td").live("click"function() {
                $("#SelectedColor").val($(this).attr("bgcolor"));
            }); 
        }); 
</script>   
<input type="text" id="SelectedColor" name="SelectedColor" readonly="readonly" />
<img src="/Content/Images/cp_button.png" alt="Pick a color" align="absmiddle" id="SelectColor" />
<span id="Sample">&nbsp;&nbsp;&nbsp;&nbsp;</span><br /><br />
<div id="Colors"></div>
 
Firstly when the user clicks on the color palette image, this will trigger the Ajax call to the server. This is done by using jQuery's $.get function. The first parameter is the URL. In ASP.NET MVC you pass in the controller/action. Once the JSON has been returned, I'm assigning it to the Colors <div> tag. 
$("#SelectColor").click(function() {
      $.get("/Color/FetchColors"nullfunction(data) {
            $("#Colors").html(eval(data));
      });
      $("#Colors").toggle();
});
Because the color selector is being generated dynamically, I can't use bind to bind an event handler to the click and mouseover events. For this to work I need to use jQuery's liveevent. The live event binds a handler to an event for all current - and future - matched elements:
$("td").live("mouseover", (function() {
      $("#Sample").css("background-color", $(this).css("background-color"));
      $(this).css("cursor""pointer");
}));
 
$("td").live("click"function() {
      $("#SelectedColor").val($(this).attr("bgcolor"));
});
Now when the user clicks on any color, the hex value will be displayed in the text box. This is a nice and easy way to add more richness to your application through jQuery. The entire source code of this article can be downloaded over here

10:36 PM by Dilip kakadiya · 0

Wednesday, November 9, 2011

Global Error Handling in ASP.NET MVC 3 with Ninject


Download the code for this blog post.
In my last blog post I explained how to decouple infrastructure concerns, such as logging, from the rest of your application using a Dependency Injection container, such as Ninject. I implemented an ILoggingService interface with an open-source logger called NLog.  In this post I will show you how to implement centralized error handling in an ASP.NET MVC 3 application, so that you can handle exceptions in one place, where you can perform logging as well as display a custom error page.
One of the worst things you can do to handle errors is place a try / catch block in every action of every controller.  Not only does it clutter the app with unnecessary code, it creates the possibility that you or another developer will forget to place the try / catch on an action and an unexpected exception will slip through.
A better approach is to handle exceptions in one place through an interception mechanism. ASP.NET MVC allows you to hook into the request pipeline by defining an Action Filter.  In fact, one such filter that comes out of the box is a HandleError attribute.  While it allows you to direct users to a particular view when certain errors occur, you cannot use it to log the exception.  The other problem is that you would have to place the attribute on every controller in your application – not much of an improvement over a proliferation of try / catch’s.
It turns out, however, that implementing IExceptionFilter is quite easy (especially if you useReflector to reverse engineer HandleErrorAttribute Winking smile).  The difference is that you can add a constructor which accepts an ILoggingService interface and is injected into the filter by your DI container.  The nice thing about Ninject is that there is an extension for MVC3 apps, which you can easily add as a NuGet package.  After installing the package, you get a NinjectMVC3.csfile placed in an App_Start folder with bootstrapping code.  There you can load a Ninject module for binding the ILoggingSservice to a concrete implementation.  I had to hunt for the source code and documentation for the Ninject.MVC3 extension, but I eventually found it hereon Github.
I implemented IExceptionFilter in a HandleExceptionFilter class, which performs logging in addition to creating a ViewResult with a custom error view.
public class HandleExceptionFilter : IExceptionFilter
{
private string _view;
private string _master;
private ILoggingService _loggingService;

public HandleExceptionFilter(ILoggingService loggingService, string master, string view)
{
_loggingService = loggingService;
_master = master ?? string.Empty;
_view = view ?? string.Empty;
}

public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}

if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled
&& filterContext.HttpContext.IsCustomErrorEnabled))
{
Exception exception = filterContext.Exception;
if ((new HttpException(null, exception).GetHttpCode() == 500))
{
// Log exception
_loggingService.Error(exception);

// Show error view
ErrorFilterHelper.SetFilerContext(filterContext, _master, _view);
}
}
}
}
I consolidated code to show the error view in an ErrorFilterHelper.
internal static class ErrorFilterHelper
{
public static void SetFilerContext(ExceptionContext filterContext, string master, string view)
{
// Show error view
string controllerName = (string)filterContext.RouteData.Values["controller"];
string actionName = (string)filterContext.RouteData.Values["action"];
var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
var result = new ViewResult
{
ViewName = view,
MasterName = master,
ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
TempData = filterContext.Controller.TempData
};
filterContext.Result = result;
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusCode = 200;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}
The next issue is how to insert HandleExceptionFilter into the pipeline.  Luckily Ninject.MVC3 comes with a BindFilter extension method which allows you to bind action filters to classes implementing IActionFilter.  To use it simply add a using directive for Ninject.Web.Mvc.FilterBindingSyntax, then supply a type argument for your filter.
private static void RegisterServices(IKernel kernel)
{
// Load logging module
kernel.Load(new LoggingModule());

// Bind exception handling filter
kernel.BindFilter<HandleExceptionFilter>(FilterScope.Global, 0)
.When(r => true)
.WithConstructorArgument("master", string.Empty)
.WithConstructorArgument("view", "Error");
}
Unhandled exceptions will now be routed to the HandleExceptionFilter, which will log the exception and take the user to the “Error” view.
This covers all unexpected exceptions.  But what if you want to show a different view for particular exceptions?  For this you will need to create a class that extends FilterAttributeand has an ExceptionType property.  In this case you will want to use an injected propertyrather than an overloaded constructor.  You will also want to set the Order property to greater than zero, so that it will intercept and deal with errors before your global error handling filter.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class HandleExceptionAttribute : FilterAttribute, IExceptionFilter
{
public HandleExceptionAttribute()
{
// Errors come here before other error filters
Order = 1;
}

[Inject]
public ILoggingService LoggingService { private get; set; }

public virtual void OnException(ExceptionContext filterContext)
{
Now you can place the HandleException attribute on an action, indicating the specific exception type you want to handle, and the name of the view you want to show the user.  If another exception occurs, HandleErrorFilter will log the error and show the default Error view.
public class HomeController : Controller
{
// GET: /
// ?errorcode=1
[HandleException(ExceptionType = typeof(CustomException), View="CustomError")]
public ActionResult Index(int? errorCode)
{
switch (errorCode.GetValueOrDefault())
{
case 1:
// This code will result in a DivideByZeroException
// No need for try/catch because exception filter will handle it
int a = 1;
int b = 0;
int result = a / b;
break;
case 2:
throw new CustomException("Expected Error");
}
return View();
}
}
In this example, the CustomException thrown in case 2 will be intercepted by HandleExceptionAttribute, where it will be logged and the exception marked as handled.  The user will then see the “CustomError” view specified as a parameter for the HandleException attribute that appears on the Home controller’s Index action. But the DivideByZeroException, which is unexpected, will be handled by the HandleErrorFilter, which will log the exception and show the default “Error” view.  To enable error filters, you need to set the mode of the <customErrors> element in web.config to “On” (set it to “RemoteOnly” if you want the unhandled exception to appear in the “Yellow Screen of Death.”)
You can download the code for this blog post here.

9:52 PM by Dilip kakadiya · 0