Encrypt Route Data in URL

17,700

Solution 1

I found a nice guide to do what I want but with QueryString BUT NOT Route Data, So I updated it to work with both QueryString and Route Data, the guide was based on creating custom Helper and custom Attribute, so put my changes easily, I will mention by code my changes:

Custom Helper

  public static MvcHtmlString EncodedActionLink(this HtmlHelper htmlHelper, string linkText, string Action, string ControllerName, string Area, object routeValues, object htmlAttributes)
    {
        string queryString = string.Empty;
        string htmlAttributesString = string.Empty;
       //My Changes
        bool IsRoute = false;
        if (routeValues != null)
        {
            RouteValueDictionary d = new RouteValueDictionary(routeValues);
            for (int i = 0; i < d.Keys.Count; i++)
            {
                 //My Changes
                if (!d.Keys.Contains("IsRoute"))
                {
                    if (i > 0)
                    {
                        queryString += "?";
                    }
                    queryString += d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i);
                }
                else
                {
                    //My Changes
                    if (!d.Keys.ElementAt(i).Contains("IsRoute"))
                    {
                        queryString += d.Values.ElementAt(i);
                        IsRoute = true;
                    }
                }
            }
        }

        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);
            }
        }


        StringBuilder ancor = new StringBuilder();
        ancor.Append("<a ");
        if (htmlAttributesString != string.Empty)
        {
            ancor.Append(htmlAttributesString);
        }
        ancor.Append(" href='");
        if (Area != string.Empty)
        {
            ancor.Append("/" + Area);
        }

        if (ControllerName != string.Empty)
        {
            ancor.Append("/" + ControllerName);
        }

        if (Action != "Index")
        {
            ancor.Append("/" + Action);
        }
        //My Changes
        if (queryString != string.Empty)
        {
            if (IsRoute == false)
                ancor.Append("?q=" + Encrypt(queryString));
            else
                ancor.Append("/" + Encrypt(queryString));
        }
        ancor.Append("'");
        ancor.Append(">");
        ancor.Append(linkText);
        ancor.Append("</a>");
        return new MvcHtmlString(ancor.ToString());
    }

Custom Attribute:

  public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        int Id;

        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 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]));
            }
        }
        else if (!HttpContext.Current.Request.Url.ToString().Contains("?"))
        {
            //if (int.TryParse(Decrypt(HttpContext.Current.Request.Url.ToString().Split('/').Last()), out Id))
            if (int.TryParse(Decrypt(HttpContext.Current.Request.Url.ToString().Split('/').Last()), out Id))
            {
                string id = Id.ToString();
                decryptedParameters.Add("id", id);
            }
        }
        else if (HttpContext.Current.Request.Url.ToString().Contains("?"))
        {
            //if (int.TryParse(Decrypt(HttpContext.Current.Request.Url.ToString().Split('/').Last().Split('?')[0]), out Id))
            if (int.TryParse(Decrypt(HttpContext.Current.Request.Url.ToString().Split('/').Last().Split('?')[0]), out Id))
            {
                string id = Id.ToString();
                if (id.Contains('?'))
                {
                    id = id.Split('?')[0];
                }
                decryptedParameters.Add("id", id);
            }

            string[] paramsArrs = HttpContext.Current.Request.Url.ToString().Split('/').Last().Split('?');
            for (int i = 1; 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);

    }

Actually My changes was not that big, so the creadit actually for this guide.

Solution 2

You can use a custom model binder for this parameter

// /Controller/Example/0000000A
public ActionResult Example([ModelBinder(typeof(EncryptDataBinder))]int id)
{
    return View(id);
}

The model binder

public class EncryptDataBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(int))
        {
            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (valueProviderResult != null)
            {
                // Use your own logic here
                bytes = ConvertUtilities.ToBytesFromHexa((string)valueProviderResult.RawValue);
                return BitConverter.ToInt32(bytes, 0);
            }
        }

        return base.BindModel(controllerContext, bindingContext);
    }
}
Share:
17,700
user2120121
Author by

user2120121

Updated on June 04, 2022

Comments

  • user2120121
    user2120121 almost 2 years

    In my ASP.NET MVC app, I want to encrypt the route data and NOT QueryString, in other word:

    I'm using the ASP.NET MVC default route pattern :

       routes.MapRoute(
                 name: "Default",
                url: "{controller}/{action}/{id}",
                 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                 namespaces: new[] { "WHATEVER" }
             ); 
    

    And I have Action Method take id Parameter:

      public ActionResult Example(int id)
      {
        return View();
      }
    

    So My Url Now to pass the data to this Action Method is:

    /Controller/Example/5

    And I want it like this

    /Controller/Example/ENCRYPTEDPARAMTER

    Thanks in Advance

  • Mesam Mujtaba
    Mesam Mujtaba over 6 years
    No suitable method found to override error at "OnActionExecuting" method,
  • Mesam Mujtaba
    Mesam Mujtaba over 6 years
    also error "Cannot convert from actionExecutingContext to HttpActionContext" at base.OnActionExecuting(filterContext);