Tuesday, May 26, 2015

Custom Action Filter in ASP.NET MVC 5


ASP.NET MVC 5 provides five different kinds of Filters. They are as follows:
  1. Authentication [Introduced in MVC5]
  2. Authorization
  3. Action
  4. Result
  5. Exception
Filters are used to inject logic at the different levels of request processing. Let us understand where at the various stages of request processing different filters get applied.
  • Authentication filter runs before any other filter or action method
  • Authorization filter runs after Authentication filter and before any other filter or action method
  • Action filter runs before and after any action method
  • Result filter runs before and after execution of any action result
  • Exception filter runs only if action methods, filters or action results throw an exception
I have tried to show the filter execution timing in context of request processing in the below diagram:
customfilterimg1
Action Filter
An action filter consists of codes that run either before or after an action runs. It can be used for tasks like logging, privileged based authorization, authentication, caching etc.
Creating a custom action filter is very easy. It can be created in four simple steps:
  1. Create a class
  2. Inherit ActionFilterAttribute class
  3. Override the OnActionExecuting method to run logic before the action method
  4. Override the OnActionExecuted method to run logic after the action method
Let us see how we can create a custom action filter. The purpose of the action filter is to find whether a logged in user belongs to a particular privileges or not. On the basis of the result, a user will access a particular action or navigate to the login action. To do this, I have created a class and extended the ActionFilterAttribute class.
As you see in the above code, the OnActionExecuting method is overridden because we want the code to execute before the action method gets executed. Once the action filter is created, it can be used in three ways:
  1. As Global filter
  2. As Controller
  3. As Action
By adding a filter to the global filter in App_Start\FilterConfig it will be available globally to the entire application.
By adding a filter to a particular Controller it will also be available to the all actions of that particular controller.
By adding a filter to a particular action it will be available to the particular action.
1
2
3
   [AuthorizationPrivilegeFilter]
        public ActionResult About()
        {

Custom HTML Helper for MVC Application

The solution to avoid this is to build a custom HTML helper to encapsulate everything and make the repetitive task less cumbersome.
Let's say we want to avoid doing this many times inside your views:
<img src="@myModel.MyObject.ImageSource", alt ="@myModel.MyObject.Imagename",
title ="@myModel.MyObject.ImageDescription" /> 
 
And instead, you want something Razor like that may take care of some logic or validations to avoid error because in the previous snippet, the ImageSource or Imagename or again the description may be null:
 @Html.Image(@myModel.MyObject.ImageSource, 
@myModel.MyObject.Imagename, @myModel.MyObject.ImageDescription) 
namespace MyNamespace 
 {  
    public static class MyHeleprs
    { 
        public static MvcHtmlString Image(this HtmlHelper htmlHelper, 
        	string source, string alternativeText)
        {
            //declare the html helper 
            var builder = new TagBuilder("image"); 
            //hook the properties and add any required logic
            builder.MergeAttribute("src", source);
            builder.MergeAttribute("alt", alternativeText);
            //create the helper with a self closing capability
            return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
        } 
    } 
}
To make this helper available in your view, add its namespace as follows:
@namespace MyNamespace 
But if you want it available in all your views, you have to add the namespace not to a specific view but to the collection of namespaces in views' web.config:
<add namespace="MyNamespace" /> 
 
Now, the Image helper is available everywhere in your views.

Custom DataAnnotations with client and server side both validation

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

namespace System.ComponentModel.DataAnnotations
{
    public class SumitValidation : ValidationAttribute, IClientValidatable
    {

        public override bool IsValid(object value)
        {
            string strValue = value as string;
            if (!string.IsNullOrEmpty(strValue))
            {

                return strValue.ToLower()=="sumit";
            }
            return true;
        }

        public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            //yield return new ModelClientValidationRule() { ValidationType = "sumitvalidation", ErrorMessage = this.ErrorMessageString };

            var modelClientValidationRule = new ModelClientValidationRule
            {
                ValidationType = "sumitvalidation",
                ErrorMessage = FormatErrorMessage(metadata.DisplayName)
            };           
            yield return modelClientValidationRule;
        }
    }
}


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


namespace MVC5_Test.Controllers
{
    public class CustomAttributeController : Controller
    {
        //
        // GET: /CustomAttribute/
        //[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
        [HttpGet]
        public ActionResult Index()
        {
           
            return View();
        }


        [HttpPost]
        public ActionResult Index(CustomValidation customValidation)
        {
          

            return View();
        }
    }
}



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

namespace MVC5_Test.Models
{
    public class CustomValidation
    {
        [Required]
        [SumitValidation]
        public string name { get; set; }
    }
}




@model MVC5_Test.Models.CustomValidation
@Scripts.Render("~/bundles/jquery")
@{
    ViewBag.Title = "Index";
}

Index




@using (Html.BeginForm())
{
    @Html.TextBoxFor(m=>m.name)
    @Html.ValidationMessageFor(m=>m.name)
    
  
}



 

Sunday, March 22, 2015

viewbag vs viewdata vs tempdata

1)TempData
Allows you to store data that will survive for a redirect. Internally it uses the Session as baking store, it's just that after the redirect is made the data is automatically evicted. The pattern is the following:
public ActionResult Foo()
{
    // store something into the tempdata that will be available during a single redirect
    TempData["foo"] = "bar";

    // you should always redirect if you store something into TempData to
    // a controller action that will consume this data
    return RedirectToAction("bar");
}

public ActionResult Bar()
{
    var foo = TempData["foo"];
    ...
}
2)ViewBag, ViewData
Allows you to store data in a controller action that will be used in the corresponding view. This assumes that the action returns a view and doesn't redirect. Lives only during the current request.
The pattern is the following:
public ActionResult Foo()
{
    ViewBag.Foo = "bar";
    return View();
}
and in the view:
@ViewBag.Foo
or with ViewData:
public ActionResult Foo()
{
    ViewData["Foo"] = "bar";
    return View();
}
and in the view:
@ViewData["Foo"]
ViewBag is just a dynamic wrapper around ViewData and exists only in ASP.NET MVC 3.
This being said, none of those two constructs should ever be used. You should use view models and strongly typed views. So the correct pattern is the following:
View model:
public class MyViewModel
{
    public string Foo { get; set; }
}
Action:
public Action Foo()
{
    var model = new MyViewModel { Foo = "bar" };
    return View(model);
}
Strongly typed view:
@model MyViewModel
@Model.Foo

After this brief introduction let's answer your question:
My requirement is I want to set a value in a controller one, that controller will redirect to ControllerTwo and Controller2 will render the View.
public class OneController: Controller
{
    public ActionResult Index()
    {
        TempData["foo"] = "bar";
        return RedirectToAction("index", "two");
    }
}

public class TwoController: Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel
        {
            Foo = TempData["foo"] as string
        };
        return View(model);
    }
}
and the corresponding view (~/Views/Two/Index.cshtml):
@model MyViewModel
@Html.DisplayFor(x => x.Foo)

There are drawbacks of using TempData as well: if the user hits F5 on the target page the data will be lost.
Personally I don't use TempData neither. It's because internally it uses Session and I disable session in my applications. I prefer a more RESTful way to achieve this. Which is: in the first controller action that performs the redirect store the object in your data store and user the generated unique id when redirecting. Then on the target action use this id to fetch back the initially stored object:
public class OneController: Controller
{
    public ActionResult Index()
    {
        var id = Repository.SaveData("foo");
        return RedirectToAction("index", "two", new { id = id });
    }
}

public class TwoController: Controller
{
    public ActionResult Index(string id)
    {
        var model = new MyViewModel
        {
            Foo = Repository.GetData(id)
        };
        return View(model);
    }
}
The view stays the same.

Tuesday, March 17, 2015

what is the benefit of bundling in asp.net mvc

Bundling and Minification is more useful in production than in development. It can significantly improve your first page hit download time.
  • Bundling reduces the number of individual HTTP requests to server by combining multiple CSS files and Javascript files into single CSS file and javascript file.
  • Minification reduces the file download size of CSS and javascript files by removing whitespace, comments and other unnecessary characters.
Such small advantages are more pronounced in a production environment than in development. So it is better to go with Bundling and Minification in production.
Specific to your question there is no palpable benefit in bundling/minification during runtime. This feature is there just to make the developer's work easier. So it is even better to go with manually bundled/minified assets in production if you are sure about what you are doing.
Update: According to MSDN there is a real benefit in bundling/minification during runtime
Bundling and minification in ASP.NET 4.5 is performed at runtime, so that the process can identify the user agent (for example IE, Mozilla, etc.), and thus, improve the compression by targeting the user browser (for instance, removing stuff that is Mozilla specific when the request comes from IE).`
The power of dynamic bundling is that you can include static JavaScript, as well as other files in languages that compiles into JavaScript.`
For example, CoffeeScript is a programming language that compiles into JavaScript

Monday, February 16, 2015

RDLC report using xsd in c# with drill down report



using Microsoft.Reporting.WebForms;
using ImprisonmentTypeTableAdapters;
protected void Page_Load(object sender, EventArgs e)
    {
     
        String userAgent = Request.ServerVariables.Get("HTTP_USER_AGENT");
        if (userAgent.Contains("MSIE 7.0"))
        {
            ReportViewer1.Style.Add("margin-bottom", "30px");
        }
    }

protected void btnReport_Click(object sender, EventArgs e)
    {
        ViewState["level"] = 0;
        getReportData();
    }
    private void getReportData()
    {

        int JailCode = Convert.ToInt32(ddlJail.SelectedValue);
        int DistCode = Convert.ToInt32(ddlDistName.SelectedValue);
        Report_ImprisonmentTimeTableAdapter ta = new Report_ImprisonmentTimeTableAdapter();
        ImprisonmentType.Report_ImprisonmentTimeDataTable dt = new ImprisonmentType.Report_ImprisonmentTimeDataTable();

        try
        {
            ta.Fill(dt, Convert.ToInt32(ddlYear.SelectedValue), Convert.ToInt32(ddlMonth.SelectedValue), Convert.ToInt32(ddlDay.SelectedValue), JailCode,DistCode);
        }
        catch
        {
            DataRow[] dr = null;
            dr = dt.GetErrors();
        }
        ReportViewer1.Visible = true;
        ReportDataSource rds = new ReportDataSource();
        ReportViewer1.Reset();
        ReportViewer1.ProcessingMode = ProcessingMode.Local;
        LocalReport rep = ReportViewer1.LocalReport;
        rep.Refresh();
        rep.ReportPath = "RDLCReport/rdlc/State_Prisoner_ImprisonmentTime.rdlc";



        rds.Name = "ImprisonmentType_Report_ImprisonmentTime";
        rds.Value = dt;
        rep.DataSources.Add(rds);


        ReportParameter[] parms = new ReportParameter[4];
        parms[0] = new ReportParameter("Year", ddlYear.SelectedValue, true);
        parms[1] = new ReportParameter("Month", ddlMonth.SelectedValue, true);
        parms[2] = new ReportParameter("Day", ddlDay.SelectedValue, true);
        parms[3] = new ReportParameter("JailName", ddlJail.SelectedItem.Text, true);
        this.ReportViewer1.LocalReport.SetParameters(parms);
        rep.Refresh();
    }


    protected void DemoDrillthroughEventHandler(object sender, DrillthroughEventArgs e)
    {
        try
        {
            if (ViewState["level"] != null)
            {
                int level = Convert.ToInt32(ViewState["level"]);
                ViewState["level"] = ++level;
                btnBack.Visible = true;
            }
            LocalReport localreport = (LocalReport)e.Report;
            ReportViewer1.Visible = true;
            ReportViewer1.Reset();
            ReportViewer1.ProcessingMode = ProcessingMode.Local;
            localreport.Refresh();
            ReportParameterInfoCollection DrillThroughValues = e.Report.GetParameters();
            string Year = DrillThroughValues["Year"].Values[0];
            string Month = DrillThroughValues["Month"].Values[0];
            string Day = DrillThroughValues["Day"].Values[0];
            string JailCode = DrillThroughValues["JailCode"].Values[0];

            Report_ImprisonmentTime_DrillTableAdapter ta = new Report_ImprisonmentTime_DrillTableAdapter();
            ImprisonmentType.Report_ImprisonmentTime_DrillDataTable dt = new ImprisonmentType.Report_ImprisonmentTime_DrillDataTable();
            try
            {
                ta.Fill(dt, Convert.ToInt32(Year), Convert.ToInt32(Month), Convert.ToInt32(Day), int.Parse(JailCode));
            }
            catch
            {
                DataRow[] dr = null;
                dr = dt.GetErrors();
            }
            ReportDataSource level1datasource = new ReportDataSource();
            localreport.ReportPath = "RDLCReport/rdlc/State_Prisoner_ImprisonmentTime_Drill.rdlc";
            level1datasource = new ReportDataSource("ImprisonmentType_Report_ImprisonmentTime_Drill", dt);
            localreport.DataSources.Clear();
            localreport.DataSources.Add(level1datasource);
            localreport.Refresh();
        }
        catch (Exception ex)
        {
        }
    }
    protected void btnBack_Click(object sender, EventArgs e)
    {
        if (ViewState["level"] != null)
        {
            int level = Convert.ToInt32(ViewState["level"]);
            if (level == 1)
            {
                getReportData();
                btnBack.Visible = false;
            }
            ViewState["level"] = --level;
        }
    }

<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>


                    ShowPrintButton="true" Visible="false" ZoomMode="Percent" OnDrillthrough="DemoDrillthroughEventHandler" >
               





ASP.NET Core

 Certainly! Here are 10 advanced .NET Core interview questions covering various topics: 1. **ASP.NET Core Middleware Pipeline**: Explain the...