ViewBag, ViewData and TempData in MVC 3

ViewData, is a dictionary object which is a derivative of the ViewDataDictionary class. It allows you to pass data to the view as key value pairs. In the view you will need to cast the value pairs to whatever type you need.

ViewBag, allows you to pass dynamic type objects to the view. It is a wrapper around the ViewData object. No casting is required.

Both ViewData & ViewBag are used to passing data between controllers and views.

Eg.

Controller,

ViewData[“Name”] = “Hello World”;

ViewBag.Name = “Hello World”;

View,

@{ var name = ViewData[“Name”] as string; }

@{ var name = ViewBag.Name; }

TempData, is to pass data between two requests. It only works when you know what the next request will be and you can access the TempData from the subsequent request’s view.

Eg.

Controller,

TempData[“Name”] = “Hello World”;

return new RedirectResult(@“~\SubsequentView\”);

View,

@{ TempData[“Name”] as string; }

Advertisements

Make use of XmlSerializer

I have a list of “Order” objects. And output a xml, here is what I did by using a XmlSerializer.

using (var memoryStream = new MemoryStream())
            {
                using (TextWriter streamWriter = new StreamWriter(memoryStream))
                {
                    System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(orders.GetType());
                    x.Serialize(streamWriter, orders);
                    return File(memoryStream.ToArray(),"xml/text");
                }
            }

Implement FormsAuthentication with custom identity in asp.net/ MVC

Sometimes you want to save more data into the authentication cookie rather than retrieve them from database all the time.

So I come up this way to create a custom Identity to allow you retrieve extra data from authentication cookies.

1. To create an identity, you need to implement the interface IIdentity.

I added Email & Roles as properties of the MyIdentity. And retrieve the data from FormsAuthenticationTicket.UserData (which is passed into MyIdentity’s constructor)


public class MyIdentity : IIdentity
 {
private System.Web.Security.FormsAuthenticationTicket ticket;

public MyIdentity(System.Web.Security.FormsAuthenticationTicket ticket)
{
this.ticket = ticket;
}

public string AuthenticationType
{
get { return "MobileOrder"; }
}

public bool IsAuthenticated
{
get { return true; }
}

public string Name
{
get { return ticket.Name; }
}

public string Email
{
get
{
string[] data = ticket.UserData.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
if (data.Length > 0)
return data[0];
else
return "";
}
}

public string[] Roles
{
get
{
string[] data = ticket.UserData.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
if (data.Length > 1)
{
string[] roles = data[1].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return roles;
}
else
return new string[] { "User" };
}
}
 }

2. I created an AuthenticationHelper to create the cookie and assign the extra data to the Ticket’s UserData.


public class AuthenticationHelper
{
public static void CreateAuthCookie(int id, string email, DateTime expiration, string[] roles, bool rememberMe)
{
FormsAuthenticationTicket authTicket = new
FormsAuthenticationTicket(1, //version
id.ToString(), // user name
DateTime.Now,
expiration, //Expiration
rememberMe, //Persistent
CreateAuthTags(email, roles));

string encTicket = FormsAuthentication.Encrypt(authTicket);

HttpContext.Current.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
}

public static string CreateAuthTags(string email, string[] roles)
{
StringBuilder sb = new StringBuilder();
sb.Append(email);
sb.Append("|");
for (int i = 0; i < roles.Length; i++)
{
sb.Append(roles[i]);
if (i < roles.Length - 1)
sb.Append(",");
}
return sb.ToString();
}
}

3. In Global.asax, register MvcApplication_PostAuthenticateRequest event to cast generic Identity to MyIdentity and assign back to the Principal in HttpContext.Current.User


public override void Init()
{
this.PostAuthenticateRequest += new EventHandler(MvcApplication_PostAuthenticateRequest);
base.Init();
}
void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
string encTicket = authCookie.Value;
if (!String.IsNullOrEmpty(encTicket))
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(encTicket);
MyIdentity id = new MyIdentity(ticket);
GenericPrincipal prin = new GenericPrincipal(id, id.Roles);
HttpContext.Current.User = prin;
}
}
}

4.  To read the MyIdentity from your pages or views

((MyIdentity)HttpContext.Current.User.Identity).Email;

Alternatively you can create PartialView for the login status and put it in _Layout.cshtml. eg.


@if(Request.IsAuthenticated) {

<ul>
<li class="small">@(((Mobile.Order.Web.Common.Identity.MyIdentity)HttpContext.Current.User.Identity).Email)</li>

|

<li>@Html.ActionLink("Account", "Index", "Account")</li>

|

<li>@Html.ActionLink("Log Off", "LogOff", new { controller = "Account", returnUrl = HttpContext.Current.Request.RawUrl })</li>

</ul>

}

else

{

<ul>

<li>

@*@Html.ActionLink("Login", "Login", "Account")*@

<a href="/Account/AjaxLogin" id="loginButton">Login</a>

</li>

|

<li>@Html.ActionLink("Register", "Index", "Register")</li>

</ul>

}

Handling images in MVC 3, ImageResult and ImageResizer

The best way to return an image to the response stream, using an ImageResult.

In the controller, load your image data to an Image object and then return a new ImageResult object as below,

Image img = LoadImage();

return new ImageResult { Image = img, ImageFormat = ImageFormat.Jpeg };

Here is the implementation of ImageResult,

public class ImageResult : ActionResult
    {
        public ImageResult() { }
        public Image Image { get; set; }
        public ImageFormat ImageFormat { get; set; }
        public override void ExecuteResult(ControllerContext context)
        {
            // verify properties 
            if (Image == null)
            {
                throw new ArgumentNullException("Image");
            }
            if (ImageFormat == null)
            {
                throw new ArgumentNullException("ImageFormat");
            }
            // output 
            context.HttpContext.Response.Clear();
            if (ImageFormat.Equals(ImageFormat.Bmp)) context.HttpContext.Response.ContentType = "image/bmp";
            if (ImageFormat.Equals(ImageFormat.Gif)) context.HttpContext.Response.ContentType = "image/gif";
            if (ImageFormat.Equals(ImageFormat.Icon)) context.HttpContext.Response.ContentType = "image/vnd.microsoft.icon";
            if (ImageFormat.Equals(ImageFormat.Jpeg)) context.HttpContext.Response.ContentType = "image/jpeg";
            if (ImageFormat.Equals(ImageFormat.Png)) context.HttpContext.Response.ContentType = "image/png";
            if (ImageFormat.Equals(ImageFormat.Tiff)) context.HttpContext.Response.ContentType = "image/tiff";
            if (ImageFormat.Equals(ImageFormat.Wmf)) context.HttpContext.Response.ContentType = "image/wmf";

            using (MemoryStream ms = new MemoryStream())
            {
                Image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                ms.WriteTo(context.HttpContext.Response.OutputStream);
            }
        }

 

If you need to resize the image before proceeding, you can use this ImageResizer class to resize image on the fly. It includes resizing by BestFit, ConstrainProportions, FixedSize, Crop.

<pre>        public static Image BestFit(Image image, int height, int width)
        {
            if (image.Height > image.Width)
            {
                return ConstrainProportions(image, height, Dimensions.Height);
            }
            else
            {
                return ConstrainProportions(image, width, Dimensions.Width);
            }
        }

        public static byte[] ImageToByteArray(System.Drawing.Image imageIn)
        {
            MemoryStream ms = new MemoryStream();
            imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            return ms.ToArray();
        }

        public static Image ByteArrayToImage(byte[] data)
        {
            ImageConverter ic = new ImageConverter();
            Image img = (Image)ic.ConvertFrom(data);
            return img;
        }

        public static Image ConstrainProportions(Image imgPhoto, int Size, Dimensions Dimension)
        {
            int sourceWidth = imgPhoto.Width;
            int sourceHeight = imgPhoto.Height;
            int sourceX = 0;
            int sourceY = 0;
            int destX = 0;
            int destY = 0;
            float nPercent = 0;

            switch (Dimension)
            {
                case Dimensions.Width:
                    nPercent = ((float)Size / (float)sourceWidth);
                    break;
                default:
                    nPercent = ((float)Size / (float)sourceHeight);
                    break;
            }

            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap bmPhoto = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
            bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);

            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

            grPhoto.DrawImage(imgPhoto,
            new Rectangle(destX, destY, destWidth, destHeight),
            new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
            GraphicsUnit.Pixel);

            grPhoto.Dispose();
            return bmPhoto;
        }

        public static Image FixedSize(Image imgPhoto, int Width, int Height)
        {
            int sourceWidth = imgPhoto.Width;
            int sourceHeight = imgPhoto.Height;
            int sourceX = 0;
            int sourceY = 0;
            int destX = 0;
            int destY = 0;

            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            nPercentW = ((float)Width / (float)sourceWidth);
            nPercentH = ((float)Height / (float)sourceHeight);

            //if we have to pad the height pad both the top and the bottom
            //with the difference between the scaled height and the desired height
            if (nPercentH < nPercentW)
            {
                nPercent = nPercentH;
                destX = (int)((Width - (sourceWidth * nPercent)) / 2);
            }
            else
            {
                nPercent = nPercentW;
                destY = (int)((Height - (sourceHeight * nPercent)) / 2);
            }

            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap bmPhoto = new Bitmap(Width, Height);
            //bmPhoto.SetResolution(2, 2);

            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.Clear(Color.Transparent);
            grPhoto.InterpolationMode = InterpolationMode.Default;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(destX, destY, destWidth, destHeight),
                new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();

            return bmPhoto;
        }
        public static Image Crop(Image imgPhoto, int Width, int Height, int destX, int destY)
        {
            int sourceWidth = imgPhoto.Width;
            int sourceHeight = imgPhoto.Height;
            int sourceX = 0;
            int sourceY = 0;

            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            nPercentW = ((float)Width / (float)sourceWidth);
            nPercentH = ((float)Height / (float)sourceHeight);

            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap bmPhoto = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
            bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);

            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(destX, destY, destWidth, destHeight),
                new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();
            return bmPhoto;
        }

        public static Image Crop(Image imgPhoto, int Width, int Height, AnchorPosition Anchor)
        {
            int sourceWidth = imgPhoto.Width;
            int sourceHeight = imgPhoto.Height;
            int sourceX = 0;
            int sourceY = 0;
            int destX = 0;
            int destY = 0;

            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            nPercentW = ((float)Width / (float)sourceWidth);
            nPercentH = ((float)Height / (float)sourceHeight);

            if (nPercentH < nPercentW)
            {
                //honrizontal
                nPercent = nPercentW;
                switch (Anchor)
                {
                    case AnchorPosition.Top:
                        destY = 0;
                        break;
                    case AnchorPosition.Bottom:
                        destY = (int)(Height - (sourceHeight * nPercent));
                        break;
                    default:
                        destY = (int)((Height - (sourceHeight * nPercent)) / 2);
                        break;
                }
            }
            else
            {
                //vertical
                nPercent = nPercentH;
                switch (Anchor)
                {
                    case AnchorPosition.Left:
                        destX = 0;
                        break;
                    case AnchorPosition.Right:
                        destX = (int)(Width - (sourceWidth * nPercent));
                        break;
                    default:
                        destX = (int)((Width - (sourceWidth * nPercent)) / 2);
                        break;
                }
            }

            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap bmPhoto = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
            bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);

            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(destX, destY, destWidth, destHeight),
                new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();
            return bmPhoto;
        }

        public enum Dimensions
        {
            Width,
            Height
        }
        public enum AnchorPosition
        {
            Top,
            Center,
            Bottom,
            Left,
            Right
        }
    }</pre>

EmailAttribute for validation using data annotations in MVC 3

Here we create an email validation attribute. By implementing the IClientValidatable interface (which will enable the Unobtrusive javascript validation) & inheriting from RegularExpressionAttribute.

    public class EmailAttribute : RegularExpressionAttribute, IClientValidatable
    {
        public EmailAttribute()
            : base(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                   @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                   @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$")
        {
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var errorMessage = FormatErrorMessage(metadata.GetDisplayName());

            yield return new EmailValidationRule(errorMessage);
        }
    }

    public class EmailValidationRule : ModelClientValidationRule
    {
        public EmailValidationRule(string errorMessage)
        {
            ErrorMessage = errorMessage;
            ValidationType = "email";
        }
    }

Then tie your validator to the model, it will validate both client & server side.

eg.

[Email]

public string Email { get;set; }

————————————————

It requires the web.config settings to enable client validations.

<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>