Skip to content

Instantly share code, notes, and snippets.

@kpmrafeeq
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kpmrafeeq/dc742ed9c52d71ab464a to your computer and use it in GitHub Desktop.
Save kpmrafeeq/dc742ed9c52d71ab464a to your computer and use it in GitHub Desktop.
DD4TFormHelper with BeginDD4TForm html extension
public static class DD4TFormHelper
{
/// <summary>
///
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="controllerName"></param>
/// <param name="area"></param>
/// <param name="additionalRouteVals"></param>
/// <param name="htmlAttributes"></param>
/// <param name="method"></param>
/// <returns></returns>
public static MvcForm BeginDD4TForm(this HtmlHelper html, string action, string controllerName, string area,
object additionalRouteVals,
IDictionary<string, object> htmlAttributes,
FormMethod method)
{
var formAction = HttpContext.Current.Request.Url.PathAndQuery;
return html.RenderForm(formAction, method, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), controllerName, action, area, additionalRouteVals);
}
/// <summary>
/// Helper method to create a new form to execute in the DD4T request pipeline against a locally declared controller
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="controllerName"></param>
/// <param name="method"></param>
/// <returns></returns>
public static MvcForm BeginDD4TForm(this HtmlHelper html, string action, string controllerName, FormMethod method)
{
return html.BeginDD4TForm(action, controllerName, null, new Dictionary<string, object>(), method);
}
/// <summary>
/// Helper method to create a new form to execute in the DD4T request pipeline against a locally declared controller
/// </summary>
/// <param name="html"></param>
/// <param name="action"></param>
/// <param name="controllerName"></param>
/// <param name="additionalRouteVals"></param>
/// <param name="htmlAttributes"></param>
/// <param name="method"></param>
/// <returns></returns>
public static MvcForm BeginDD4TForm(this HtmlHelper html, string action, string controllerName,
object additionalRouteVals,
IDictionary<string, object> htmlAttributes,
FormMethod method)
{
return html.BeginDD4TForm(action, controllerName, "", additionalRouteVals, htmlAttributes, method);
}
public static string DecryptWithMachineKey(this string value)
{
if (value == null)
return null;
string[] parts = value.Split('\n');
StringBuilder decryptedValue = new StringBuilder();
foreach (var part in parts)
{
decryptedValue.Append(FormsAuthentication.Decrypt(part.TrimEnd()).UserData);
}
return decryptedValue.ToString();
}
private static MvcForm RenderForm(this HtmlHelper htmlHelper,
string formAction,
FormMethod method,
IDictionary<string, object> htmlAttributes,
string controller,
string action,
string area,
object additionalRouteVals = null)
{
//ensure that the multipart/form-data is added to the html attributes
if (htmlAttributes.ContainsKey("enctype") == false)
{
htmlAttributes.Add("enctype", "multipart/form-data");
}
var tagBuilder = new TagBuilder("form");
tagBuilder.MergeAttributes(htmlAttributes);
// action is implicitly generated, so htmlAttributes take precedence.
tagBuilder.MergeAttribute("action", formAction);
// method is an explicit parameter, so it takes precedence over the htmlAttributes.
tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true);
var traditionalJavascriptEnabled = htmlHelper.ViewContext.ClientValidationEnabled && htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled == false;
if (traditionalJavascriptEnabled)
{
// forms must have an ID for client validation
tagBuilder.GenerateId("form" + Guid.NewGuid().ToString("N"));
}
htmlHelper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));
//new DD4TForm:
var theForm = new DD4TForm(htmlHelper.ViewContext, controller, action, area, method, additionalRouteVals);
if (traditionalJavascriptEnabled)
{
htmlHelper.ViewContext.FormContext.FormId = tagBuilder.Attributes["id"];
}
return theForm;
}
internal class DD4TForm : MvcForm
{
/// <summary>
/// Creates an DD4TForm
/// </summary>
/// <param name="viewContext"></param>
/// <param name="controllerName"></param>
/// <param name="controllerAction"></param>
/// <param name="area"></param>
/// <param name="method"></param>
/// <param name="additionalRouteVals"></param>
public DD4TForm(
ViewContext viewContext,
string controllerName,
string controllerAction,
string area,
FormMethod method,
object additionalRouteVals = null)
: base(viewContext)
{
_viewContext = viewContext;
_method = method;
_encryptedString = CreateEncryptedRouteString(controllerName, controllerAction, area, additionalRouteVals);
}
private readonly ViewContext _viewContext;
private readonly FormMethod _method;
private bool _disposed;
private readonly string _encryptedString;
protected override void Dispose(bool disposing)
{
if (this._disposed)
return;
this._disposed = true;
_viewContext.Writer.Write("<input name='tprt' type='hidden' value='" + _encryptedString + "' />");
base.Dispose(disposing);
}
}
internal static string CreateEncryptedRouteString(string controllerName, string controllerAction, string area, object additionalRouteVals = null)
{
//need to create a params string as Base64 to put into our hidden field to use during the routes
var routeParams = string.Format("c={0}&a={1}&ar={2}",
HttpUtility.UrlEncode(controllerName),
HttpUtility.UrlEncode(controllerAction),
area);
var additionalRouteValsAsQuery = additionalRouteVals != null ? additionalRouteVals.ToDictionary<object>().ToQueryString() : null;
if (additionalRouteValsAsQuery.IsNullOrWhiteSpace() == false)
routeParams += "&" + additionalRouteValsAsQuery;
return routeParams.EncryptWithMachineKey();
}
internal static IDictionary<string, TVal> ToDictionary<TVal>(this object o, params string[] ignoreProperties)
{
if (o != null)
{
var props = TypeDescriptor.GetProperties(o);
var d = new Dictionary<string, TVal>();
foreach (var prop in props.Cast<PropertyDescriptor>().Where(x => !ignoreProperties.Contains(x.Name)))
{
var val = prop.GetValue(o);
if (val != null)
{
d.Add(prop.Name, (TVal)val);
}
}
return d;
}
return new Dictionary<string, TVal>();
}
/// <summary>
/// Encrypt the string using the MachineKey in medium trust
/// </summary>
/// <param name="value">The string value to be encrypted.</param>
/// <returns>The encrypted string.</returns>
public static string EncryptWithMachineKey(this string value)
{
if (value == null)
return null;
string valueToEncrypt = value;
List<string> parts = new List<string>();
const int EncrpytBlockSize = 500;
while (valueToEncrypt.Length > EncrpytBlockSize)
{
parts.Add(valueToEncrypt.Substring(0, EncrpytBlockSize));
valueToEncrypt = valueToEncrypt.Remove(0, EncrpytBlockSize);
}
if (valueToEncrypt.Length > 0)
{
parts.Add(valueToEncrypt);
}
StringBuilder encrpytedValue = new StringBuilder();
foreach (var part in parts)
{
var encrpytedBlock = FormsAuthentication.Encrypt(new FormsAuthenticationTicket(0, string.Empty, DateTime.Now, DateTime.MaxValue, false, part));
encrpytedValue.AppendLine(encrpytedBlock);
}
return encrpytedValue.ToString().TrimEnd();
}
public static string ToQueryString(this IDictionary<string, object> d)
{
if (!d.Any()) return "";
var builder = new StringBuilder();
foreach (var i in d)
{
builder.Append(String.Format("{0}={1}&", HttpUtility.UrlEncode(i.Key), i.Value == null ? string.Empty : HttpUtility.UrlEncode(i.Value.ToString())));
}
return builder.ToString().TrimEnd('&');
}
public static bool IsNullOrWhiteSpace(this string str)
{
return (str == null) || (str.Trim().Length == 0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment