HTML.textBoxFor(x=>x.Price, Disabled = True) Doesn't Post The Value To The Controller Post Action!
Solution 1:
You can also make them readonly rather than disabling them. On the other note, I think @Chris solution is better, that way your modified data will be posted back.
Solution 2:
You can use Html.HiddenFor() and use a <span>
or <div>
instead. Their values will then be posted back.
Solution 3:
Well, this is what i did up to now,
i didn't succeed to make a good, easy to use, readonly protection using encryption,
but i did manage to do something that i think might just do.
how it works:
When you use
LockObject(o)
an object, itterate the properties that have definedProtectedAttribute
defined for.add the locked value to a list, specially made for this field.
! the list is kept in the user session (on the server side)when the user submits the form,
IsValid
checks to see if the value is in the list of locked values. if yes, then it is all ok. otherwise, it must have been changed somehow.
! the number of values is not that big, and is temporary to the session, but if it is bothering someone, a simple lockList.remove(node);
can easly be added when a value is validated.
Note: this can cause problem when the user uses Back buttons or Resubmit a form using Refresh.
tell me if you find any problems that this model does not take into account...
+ the Equalization is very naive, so it works only with value-types for time be.
Code:
Created an attribute named ProtectedAttribute
:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
public class ProtectedPropertyAttribute : ValidationAttribute
{
private static Dictionary<string, LinkedList<object>> savedValues;
static ProtectedPropertyAttribute()
{
savedValues = (Dictionary<string, LinkedList<object>>)HttpContext.Current.Session["ProtectedAttributeData"];
if (savedValues != null)
return;
savedValues = new Dictionary<string, LinkedList<object>>();
HttpContext.Current.Session.Add("ProtectedAttributeData", savedValues);
}
public static void LockObject(object obj)
{
Type type = obj.GetType();
foreach (PropertyInfo property in type.GetProperties())
{
LockProperty(obj, property);
}
}
public static void LockProperty(object obj, PropertyInfo property)
{
ProtectedPropertyAttribute protectedAttribute =
(ProtectedPropertyAttribute)
property.GetCustomAttributes(typeof (ProtectedPropertyAttribute), false).FirstOrDefault();
if (protectedAttribute == null)
return;
if(protectedAttribute.Identifier == null)
protectedAttribute.Identifier = property.Name;
LinkedList<object> list;
if (!savedValues.TryGetValue(protectedAttribute.Identifier, out list))
{
list = new LinkedList<object>();
savedValues.Add(protectedAttribute.Identifier, list);
}
list.AddLast(property.GetValue(obj, null));
}
public string Identifier { get; set; }
public ProtectedPropertyAttribute()
{
}
public ProtectedPropertyAttribute(string errorMessage) : base(errorMessage)
{
}
public ProtectedPropertyAttribute(Func<string> errorMessageAccessor) : base(errorMessageAccessor)
{
}
protected override ValidationResult IsValid (object value, ValidationContext validationContext)
{
LinkedList<object> lockedValues;
if (Identifier == null)
Identifier = validationContext.DisplayName;
if (!savedValues.TryGetValue(Identifier, out lockedValues))
return new ValidationResult(FormatErrorMessage(validationContext.MemberName), new[] { validationContext.MemberName });
bool found = false;
LinkedListNode<object> node = lockedValues.First;
while (node != null)
{
if(node.Value.Equals(value))
{
found = true;
break;
}
node = node.Next;
}
if(!found)
return new ValidationResult(FormatErrorMessage(validationContext.MemberName), new[] { validationContext.MemberName });
return ValidationResult.Success;
}
}
place this attribute on any property of your model just as any other validation.
public class TestViewModel : Controller
{
[ProtectedProperty("You changed me. you bitch!")]
public string DontChangeMe { get; set; }
public string ChangeMe { get; set; }
}
in the controller, after you are finished with the viewmodel object,
you call ProtectedAttribute.LockObject(myViewModel)
public class TestController : Controller
{
public ActionResult Index()
{
TestViewModel vm = new TestViewModel {ChangeMe = "a1", DontChangeMe = "b1"};
ProtectedPropertyAttribute.LockObject(vm);
return View(vm);
}
public string Submit(TestViewModel vm)
{
string errMessage;
return !validate(out errMessage) ? "you are a baaad, man." + errMessage : "you are o.k";
}
private bool validate(out string errormessage)
{
if (ModelState.IsValid)
{
errormessage = null;
return true;
}
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, ModelState> pair in ModelState)
{
sb.Append(pair.Key);
sb.Append(" : <br/>");
foreach (ModelError err in pair.Value.Errors)
{
sb.Append(" - ");
sb.Append(err.ErrorMessage);
sb.Append("<br/>");
}
sb.Append("<br/>");
}
errormessage = sb.ToString();
return false;
}
}
Post a Comment for "HTML.textBoxFor(x=>x.Price, Disabled = True) Doesn't Post The Value To The Controller Post Action!"