Here is my scenario: I have a model called MaterialPaymentRequest
. It consists of several MaterialPaymentRequestSubItem
so PaymentRequest
is parent and MaterialPaymentRequestSubItem
are its children. Consider when I have a MaterialPaymentRequest
and I want to add a child to it. Currently its method inside MaterialPaymentRequestSbuItemController
looks like this:
public ActionResult CreateChild(int parentId)
{
if (parentId==null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var parenetRequest = (from request in db.MaterialPaymentRequests
where request.Id==parentId
select request);
ViewBag.MaterialPaymentRequestId = new SelectList(parenetRequest, "Id", "Description", parentId);
ViewBag.ParentID = parentId;
return View();
}
My problem is inside view, user can change its parent since I have a dropdown which I cannot freeze it or make it readonly:
@Html.DropDownList("MaterialPaymentRequestId", String.Empty)
I've tried to use a ViewModel
and after post I set parentID of my chil however this way I don't know how to pass ParentId to http-post controller method.
My postback method before using ViewMode is like this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateChild([Bind(Include = "Id,Name,Unit,UnitPrice,MaterialPaymentRequestId,Quantity")] MaterialPaymentRequestSubItem materialpaymentrequestsubitem)
{
if (ModelState.IsValid)
{
...
}
....
}
I've seen methods like this which use Html.Hidden
but i think it is not secure enough since user can manipulate information at user-side.
Are there any better method to do this?
Can I pass information to a controller which accept parentID as parameter with declarion like this?
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateChild(int parentID, [Bind(Include = "Id,Name,Unit,UnitPrice,MaterialPaymentRequestId,Quantity")] MaterialPaymentRequestSubItem materialpaymentrequestsubitem)
{
if (ModelState.IsValid)
{
...
}
....
}
To make a HTML helper input control read only on client side, use the following:
@Html.DropDownList("MaterialPaymentRequestId", String.Empty, new { @readonly = "readonly" })
I suggest you to maintain parentId content state in server side with Session variable if you don't want to use client-side hidden fields.
Session["parentId"] = parentId;
// just an example to extract Session variable
int parentId = Session["parentId"] != null ? Convert.ToInt32(Session["ParentId"]) : return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
However if you need the hidden field inside your view, use encoded text in hidden field with validation schema against its value (eg Base64 or better encodings), thus any user visiting your site can't easily alter the value in client-side.
View:
@Html.Hidden("ParentID", @ViewBag.ParentID);
// or if you have a viewmodel, pass viewmodel's value here
@Html.HiddenFor(model => model.ParentID);
Controller method:
public ActionResult CreateChild(int parentId)
{
...
// convert parentId into Base64
ViewBag.ParentID = Convert.ToBase64String(parentId);
return View(ViewBag); // model binding
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateChild([Bind(Include = "Id,Name,Unit,UnitPrice,MaterialPaymentRequestId,Quantity,ParentID")] MaterialPaymentRequestSubItem materialpaymentrequestsubitem)
{
...
// get Parent ID
int parentId = (int)Convert.FromBase64String(ParentID);
// write your own algorithm to validate hidden field's value
...
if (ModelState.IsValid)
{
// redirect to create child elements
return RedirectToAction("CreateChild", "Controller", new { @id = parentId });
}
}
Hope this explanation useful for you, CMIIW.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.