It has been some time i try figuring out this!
Generally: i want to get a “Readonly, Hidden” Property from my Form.
I Trimmed all that is unncessey from the example:
i have the following Model
public class ChangeOrderDetailModel
{
...
...
[ReadOnly(true)]
public int OrderId { get; set; }
}
and in the View:
@using (Html.BeginForm("SubmitChangeOrder", "Order"))
{
@Html.AntiForgeryToken()<br/>
@Html.HiddenFor(o => o.OrderId) <br />
...
...
}
Now:
-
in the View HTML, there is a hidden field for OrderID…
-
I dont want anyone to change “OrderID” cause it can cause security issues.
-
I need the OrderID number at the form submit…
-
Problem When the form is submitted to the Controller
OrderController.SubmitChangeOrder(ChangeOrderDetailModel mdl){}
i see thatmdl.OrderIDis always = 0. -
When I remove the
ReadOnly(true)attribute from the propertie, everything works ok, but anyone can change the value of the field using simple JS, which is VERY BAD.
and i dont want to relay only on a hash token cause it is easly broken too 🙁
Why is it working like this?
Am i missing something, a better way to achive what i like?
note: there might be several change orders going on in parallel so session is kinda problematic.
Thanks to all.
By using [Readonly(true)] you are explicitly instructing the model binder not to bind the field to the property of the model. By rendering the property using
Html.HiddenForhave already achieved what you want in your rendered html. You can include a second parameter in your controller action asint OrderIdand the model binder will bind the value on to that variableA rogue user may still be able to edit OrderId. One way to guard it against such action is to encrypt OrderId and use the encrypted value in the model and subsequently on the page. Then once the postback happens, you will decrypt the encrypted OrderId. Encryption and decryption could be encapsulated in to the model itself
@TomerW, if I understood your question correctly, your core issue is that a rogue user can change the value of OrderId at the client side, My suggestion is not to render OrderId in its bare form, but encrypt it at the server side using a key only known at the server. You should render the encrypted value in HTML as a hidden filed. A rogue user may still attempt to change the associated value, but decryption will fail and you will know that someone has tried to fiddle with your value. Following is a stub implementation,
In your view model, use
@Html.HiddenFor(o => o. OrderIdEnc). You can use standard windows crypto to do the encryption and decryption.To be extremely safe, you can use a different key for each req/response session. This will prevent a more advanced rogue user from replacing OrderIdEnc with an older version.
I am sure that there may be other solutions, but above is a pattern that I have used many times and has worked
Cheers