How to encrypt the query string ID in MVC 4 ActionLink
Here are a couple of simple methods you can use to encode/decode. The encoded value is not secure, and as you can see, decoding it is trivial. If your goal is to obfuscate the id, this will work. If you need to secure it, you should take a different approach.
public string Encode( string encodeMe )
{
byte[] encoded = System.Text.Encoding.UTF8.GetBytes( encodeMe );
return Convert.ToBase64String( encoded );
}
public static string Decode( string decodeMe )
{
byte[] encoded = Convert.FromBase64String( decodeMe );
return System.Text.Encoding.UTF8.GetString( encoded );
}
So you could place these methods in your controller, and pass the encoded TechId to the view with viewBag
int techId = 1;
var encoded = Encode(id.ToString());
ViewBag.Encoded = encoded;
And then to use it in your link
@Html.ActionLink(techName, "Details","Home", new { TopicID = ViewBag.Encoded },null)
(Though, you should really consider using a view model. ViewBag, while a convienent and easy way to pass data to the view, is not considered to be best practice. Becoming comfortable with view models and strongly typed views will make your mvc life much easier in the future. Not to mention, produce cleaner and more maintainable code for those that follow you.)
Add A Folder with two classes
Class 1 : EncryptedActionParameterAttribute
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Web;
using System.Web.Mvc;
namespace MVCInvoicClient.Extensions
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class EncryptedActionParameterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Dictionary<string, object> decryptedParameters = new Dictionary<string, object>();
if (HttpContext.Current.Request.QueryString.Get("q") != null)
{
string encryptedQueryString = HttpContext.Current.Request.QueryString.Get("q");
string decrptedString = Decrypt(encryptedQueryString.ToString());
string[] paramsArrs = decrptedString.Split('?');
for (int i = 0; i < paramsArrs.Length; i++)
{
string[] paramArr = paramsArrs[i].Split('=');
decryptedParameters.Add(paramArr[0], Convert.ToInt32(paramArr[1]));
}
}
for (int i = 0; i < decryptedParameters.Count; i++)
{
filterContext.ActionParameters[decryptedParameters.Keys.ElementAt(i)] = decryptedParameters.Values.ElementAt(i);
}
base.OnActionExecuting(filterContext);
}
private string Decrypt(string encryptedText)
{
string key = "jdsg432387#";
byte[] DecryptKey = { };
byte[] IV = { 55, 34, 87, 64, 87, 195, 54, 21 };
byte[] inputByte = new byte[encryptedText.Length];
DecryptKey = System.Text.Encoding.UTF8.GetBytes(key.Substring(0, 8));
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
inputByte = Convert.FromBase64String(encryptedText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(DecryptKey, IV), CryptoStreamMode.Write);
cs.Write(inputByte, 0, inputByte.Length);
cs.FlushFinalBlock();
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
return encoding.GetString(ms.ToArray());
}
}
}
Class 2 : MyExtensions
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MVCInvoicClient.Extensions
{
public static class MyExtensions
{
public static MvcHtmlString EncodedActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
{
string queryString = string.Empty;
string htmlAttributesString = string.Empty;
if (routeValues != null)
{
RouteValueDictionary d = new RouteValueDictionary(routeValues);
for (int i = 0; i < d.Keys.Count; i++)
{
if (i > 0)
{
queryString += "?";
}
queryString += d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i);
}
}
if (htmlAttributes != null)
{
RouteValueDictionary d = new RouteValueDictionary(htmlAttributes);
for (int i = 0; i < d.Keys.Count; i++)
{
htmlAttributesString += " " + d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i);
}
}
//<a href="/Answer?questionId=14">What is Entity Framework??</a>
StringBuilder ancor = new StringBuilder();
ancor.Append("<a ");
if (htmlAttributesString != string.Empty)
{
ancor.Append(htmlAttributesString);
}
ancor.Append(" href='");
if (controllerName != string.Empty)
{
ancor.Append("/" + controllerName);
}
if (actionName != "Index")
{
ancor.Append("/" + actionName);
}
if (queryString != string.Empty)
{
ancor.Append("?q=" + Encrypt(queryString));
}
ancor.Append("'");
ancor.Append(">");
ancor.Append(linkText);
ancor.Append("</a>");
return new MvcHtmlString(ancor.ToString());
}
private static string Encrypt(string plainText)
{
string key = "jdsg432387#";
byte[] EncryptKey = { };
byte[] IV = { 55, 34, 87, 64, 87, 195, 54, 21 };
EncryptKey = System.Text.Encoding.UTF8.GetBytes(key.Substring(0, 8));
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
byte[] inputByte = Encoding.UTF8.GetBytes(plainText);
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, des.CreateEncryptor(EncryptKey, IV), CryptoStreamMode.Write);
cStream.Write(inputByte, 0, inputByte.Length);
cStream.FlushFinalBlock();
return Convert.ToBase64String(mStream.ToArray());
}
}
}
Controller
Add this line above the controller class Example for your Index
[EncryptedActionParameter]
In your View
@Html.EncodedActionLink("Download Invoice", "FileDownload","DataFiles", new { id = item.DataFilesID }, null)
add a using statement
@using MVCInvoicClient.Extensions