简体   繁体   中英

ASP.Net MVC: pass information to HTTPost Controller

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM