Tuesday, June 19, 2012

MVC- ViewData and ViewBag


Difference between ViewData and ViewBag

Both objects ViewData and ViewBag used to pass data from Controller to View and From View to Controller.
ViewData is a dictionary object where you can put data, which then becomes available to the view.
ViewData is a derivative of the ViewDataDictionary class, so you can access by the familiar “key/value” syntax.

ViewBag uses the dynamic feature and it  allows an object to dynamically have properties added to it.
As ViewBag is a dynamic property, instead of writing ViewData[“Value”]=”someValue”, we can write ViewBag.Value=”SomeValue”.
 We can just get or set properties and it will resolve them dynamically at run time.
ViewBag internally uses ViewData to store the values,
 ViewBag properties are stored as name/value pairs in the ViewData dictionary.
Note :  Values stored in ViewData can be accessed by ViewBag and  vice versa.

Example below

Controller

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

namespace MvcTextApplication.Controllers
{
    public class ViewBagController : Controller
    {
       
        public ActionResult VDataSample1()
        {
            List<string> Prices = new List<string>();
            Prices.Add("109.09");
            Prices.Add("110.98");
          
            ViewData["Prices"] = Prices;
            ViewData["FundName"] = "US Microcap";
            ViewData["FundClass"] = "Class A";
         
            List<string> Currency = new List<string>();
            Currency.Add("USD");
            Currency.Add("GBP");
            Currency.Add("EURO");
            ViewBag.CurrenyList = Currency;

            ViewBag.FundDate = DateTime.Now.ToString(); 
        

            return View();
        }

    }
}


View

<h2>Simple View data Sample</h2>
<p>
    <b style="color:Red"><u> Fund Details using View Data</u></b><br />
    <b>Fund Name  :  <%: ViewData["Fund Name"]%></b><br />
    <b>Fund Class :  <%: ViewData["FundClass"]%></b><br />
    <b>FundDate(storen in ViewBag) :  <%: ViewData["FundDate"]%></b>     
</p>

<b style="color:Red"><u> Fund Prices</u></b>
 
<ul id="Funds">
<% foreach (var price in ViewData["Prices"] as List<string>)
   { %>
    <li>
       <%: price %>
    </li>
<% } %>
</ul>

<b style="color:Red"><u> View Bag Currency LIST</u></b>
<ul id="Ul2">
<% foreach (var cur in ViewData["CurrenyList"] as List<string>)
   { %>
    <li>
       <%: cur%>
    </li>
<% } %>
</ul>

<hr />

<p>
    <b style="color:Red"><u> Fund Details using ViewBag</u></b><br />
    <b>Fund Name  :  <%: ViewBag.FundName %></b><br />
    <b>Fund Class : <%: ViewBag.FundClass%></b><br /> 
    <b style="color:Red"><u> Fund Prices</u></b>
</p>

<ul id="Ul1">
<% foreach (var price in ViewBag.Prices)
   { %>
    <li>
       <%: price %>
    </li>
<% } %>
</ul>
<b style="color:Red"><u>Currency List</u></b>
<ul id="Ul3">
<% foreach (var cur in ViewBag.CurrenyList)
   { %>
    <li>
       <%: cur %>
    </li>
<% } %>
</ul>



OutPut :


Monday, June 18, 2012

MVC-Authentication-Authorization




MVC authentication and authorization, custom Filters  example

Login Class

public class UserLogon
{
    [Required]
    [Display(Name = "User Login")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

}


Account Controller 

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


namespace MvcTextApplication.Controllers
{
    public class AccountController : Controller
    {
        public ActionResult LogOn()
        {
            return View();
        }

        //
        // POST: /Account/LogOn

        [HttpPost]
        public ActionResult LogOn(UserLogon model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
              
                 string Role = "";

                // Passw0rd can be get from database
                // I am assigning one common password
                 string password = "common";

                // Role can be get from database also
                // I am assigning roles manually
                if (model.UserName == "adminuser")
                {
                    Role = "Admin";

                }
                else if (model.UserName == "staffuser")
                {
                    Role = "SU";
                }
                else
                {
                    Role = "Others";
                }

                if (string.IsNullOrEmpty(model.UserName) || string.IsNullOrEmpty(model.Password))
                {
                    ModelState.AddModelError("", "The user login or password provided is incorrect.");
                }

                // we are checking here if Passowrd entered by user is same as our password eg: common
                if (model.Password == password)
                {

                    // create FormsAuthenticationTicket
                            var authTicket = new FormsAuthenticationTicket(
                                            1,                             // version
                                            model.UserName,                 // user name
                                            DateTime.Now,                  // created
                                            DateTime.Now.AddMinutes(20),   // expires
                                            false,                         // persistent?
                                            Role.ToString()               // can be used to store roles
                                            );

                    string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
                    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
                    System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);

                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                    {                      
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        
                        return RedirectToAction("../Security/Index");
                      
                    }
                }
                else
                {
                    ModelState.AddModelError("", "The password provided is incorrect.");
                }
            }

          
            return View(model);
        }


        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();

            return RedirectToAction("Index", "Home");
        }
    }
}


Login View

<h2>LogOn</h2>

<script src="<%: Url.Content("~/Scripts/jquery.validate.min.js") %>" type="text/javascript"></script>
<script src="<%: Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js") %>" type="text/javascript"></script>

<% using (Html.BeginForm()) { %>
    <%: Html.ValidationSummary(true) %>
    <fieldset>
        <legend>UserLogon</legend>

        <div class="editor-label">
            <%: Html.LabelFor(model => model.UserName) %>
        </div>
        <div class="editor-field">
            <%: Html.EditorFor(model => model.UserName) %>
            <%: Html.ValidationMessageFor(model => model.UserName) %>
        </div>

        <div class="editor-label">
            <%: Html.LabelFor(model => model.Password) %>
        </div>
        <div class="editor-field">
            <%: Html.EditorFor(model => model.Password) %>
            <%: Html.ValidationMessageFor(model => model.Password) %>
        </div>

        <p>
            <input type="submit" value="Login" />
        </p>
    </fieldset>
<% } %>

<div>
    <%: Html.ActionLink("Back to List", "Index") %>
</div>






We can see in Controller class that if user Login adminuser then role  would be Admin and if user Login is  staffuser then role would be SU other role would be Others 






Custom Error View :
 
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MasterPage.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">

<h2>Custom Error Page </h2> <br /><br />

 <%= (string)ViewBag.ErrorMessage %>

</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder2" runat="server">
</asp:Content>

 








Security Controller class:


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

namespace MvcTextApplication.Controllers
{
    [HandleError]
    public class SecurityController : Controller
    {
        //Can be accessed by anonymous users    
        public ActionResult Index()
        {
            ViewData["Message"] = "Welcome to My website";
            return View();
        }

       [CustomAuthorizeSecod]
        public ActionResult About()
        {
            ViewData["Message"] = "Welcome to My website About Page";
            return View();
        }

        
        [Authorize]   
        public ActionResult AuthenticatedUsers()
        {
            ViewData["Message"] = "Welcome to My website Authenticated Users Page";
            return View();
        }

        [Authorize(Users = "staffuser")]
        public ActionResult Users()
        {
            ViewData["Message"] = "Welcome to My website Authenticated Specific users";
            return View();
        }


       
        [Authorize(Roles = "Admin,SU")]     
        public ActionResult Roles()
        {
            ViewData["Message"] = "Welcome to My website Authenticated Users admin adn SU Page";
            return View();
        }


    }
}



CustomAuthorizeSecod  Class :





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


    public class CustomAuthorizeSecod : FilterAttribute, IAuthorizationFilter
    {

        public void OnAuthorization(AuthorizationContext filterContext)
        {

         
                var Controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
                var Action = filterContext.ActionDescriptor.ActionName;
                var User = filterContext.HttpContext.User;
                var IP = filterContext.HttpContext.Request.UserHostAddress;
              

                if (filterContext.HttpContext.Request.IsAuthenticated)
                {

                    if (filterContext.HttpContext.User.IsInRole("Admin"))
                    {
                        return;      
                    }
                    else
                    {

                           ViewResult result = new ViewResult();
                            result.ViewName = "../Error/CustomError";
                            result.ViewBag.ErrorMessage = "You are not authenticated. Please log-in and try again!";
                            filterContext.Result = result;
                       // }
                    }
                }
                else
                {

                    ViewResult result = new ViewResult();
                    result.ViewName = "../Error/CustomError";
                    result.ViewBag.ErrorMessage = "You are not authenticated. Please log-in and try again!";
                    filterContext.Result = result;
                }         

        }

    }




Important Steps:

Webconfig File :  Add  following code

    <authentication mode="Forms">
      <forms loginUrl="~/Account/Logon" timeout="2880" />
    </authentication>
   

Global File : Add following code
  protected void Application_AuthenticateRequest(Object sender, EventArgs e)
        {
            HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
            if (authCookie == null || authCookie.Value == "")
                return;

            FormsAuthenticationTicket authTicket;
            try
            {
                authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            }
            catch
            {
                return;
            }

            // retrieve roles from UserData
            string[] roles = authTicket.UserData.Split(';');

            if (Context.User != null)
                Context.User = new GenericPrincipal(Context.User.Identity, roles);
        }



Login as AdminUser 
 Role =Admin





Redirected to following screen 


 Type following URL



  Which will call Following method


        [Authorize(Users = "staffuser")]
        public ActionResult Users()
        {
            ViewData["Message"] = "Welcome to My website Authenticated Specific users";
            return View();
        }

Only  staffuser can access this Action method so browser redirect to Logon view
which we specify in WEBCONFIG FILE