How to send a model property value from a view to controller - asp.net-mvc

I have a view tied with a Item model that displays a shopping item. I want to a add a quantity text field and submit the itemID and quantity to a controller. I am using an AJAX form.
AJAX form:
#using (Ajax.BeginForm("AddToCart", "PizzaBasket",
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
OnFailure = "searchFailed",
LoadingElementId = "ajax-loader",
UpdateTargetId = "basketSummary",
}))
{
#Html.HiddenFor(id => id.ItemId, new { #class = "id" })
<input type="hidden" name="id" class="id")/>
<label for="quantity">Quantity</label>
<input type="text" name="quantity" size="5"/>
<input type="submit" value="Add to Cart" />
<img id="ajax-loader" src="#Url.Content("~/Content/Images/ajax-loader.gif")" style="display:none"/>
}
Controller action:
public ActionResult AddToCart(String id, String quantity) {
/*Add to cart*/
return RedirectToAction("Index");
}
However, the id value is not getting submitted. Need to find out how to pass the id value from the AJAX form to the controller. Please note, that in the same file #Model.itemId is working fine.

This line:
#Html.HiddenFor(id => id.ItemId, new { #class = "id" })
needs to be inside your Using statement. The same goes for your submit button/input. In order for the ajax form to submit properly those two must be inside the Using block.

You can use Forms Collection as follows,
View :
#Html.HiddenFor(m=>m.ProductID)
Controller:
[HttpPost]
public void HiddenForExample(FormCollection collection)
{
string productid = Convert.ToString(collection["ProductID"]);
}

Here is the control that will post the id to your controller (and take note of the parentheses, it should be removed):
<input type="hidden" name="id" class="id") />
It is this control that the model binder will use to populate the String id argument in your controller action. Since you are hard-coding it, the only way to manipulate its value prior to posting to the controller is with javascript. Are you certain you are doing that? Otherwise the value will come across as empty.
Also, for your Ajax options, you should set your method to post:
HttpMethod = "POST"
I can't see what HTML Action your particular controller action expects, but I'm guessing it has been decorated with [HttpPost]

Related

Passing route values to Html.BeginForm

I want the form to pass the values from the hidden inputs to the server and I also expected it to build the URL as
"localhost:9392/Ranking/Index/2?rankingType=SOMEVALUE&ageGroup=SOMEVALUE&week=SOMEVALUE"
but it shows like "localhost:9392/Ranking/Index/2?rankingType=rankingTypeID&ageGroup=ageGroupID&week=week"
#using (Html.BeginForm("Index", "Ranking", new { id = Model.CurrentRanking, rankingType = "rankingTypeID", ageGroup = "ageGroupID", week = "week"}, FormMethod.Post, new { id = "ageGroupForm" }))
{
<input id="ageGroupID" name="ageGroup" hidden />
<input id="rankingTypeID" name="rankingType" hidden />
<input id="week" name="week" hidden />
}
Why is that ? How do I pass the values and also have them show up as query string ?
Try this code:
#using (Html.BeginForm("Index", "Ranking"))
{
<input id="ageGroupID" name="ageGroup" hidden />
<input id="rankingTypeID" name="rankingType" hidden />
<input id="week" name="week" hidden />
}
and in your action method, decorate it like:
public ActionResult Index(string ageGroupID, string rankingTypeID, string week){}
but it shows like "localhost:9392/Ranking/Index/2?rankingType=rankingTypeID&ageGroup=ageGroupID&week=week"
That's because those are exactly the string values you're using:
new { id = Model.CurrentRanking, rankingType = "rankingTypeID", ageGroup = "ageGroupID", week = "week"}
It's not really clear why you're trying to set query string values for the exact form inputs you already have:
<input id="ageGroupID" name="ageGroup" hidden />
<input id="rankingTypeID" name="rankingType" hidden />
<input id="week" name="week" hidden />
If what you're trying to accomplish is to have those values be on the query string (as a GET request) instead of in the request body (as a POST request) then all you have to do is change your form method to a GET:
#using (Html.BeginForm("Index", "Ranking", new { id = Model.CurrentRanking }, FormMethod.Get, new { id = "ageGroupForm" }))
HTML form inputs are automatically added to the request, that's how forms work. You don't need to try to do it manually.
Though it's strange that you're doing this at all. Your inputs are hidden, which usually means you don't want to concern the user with them. But you're also showing them on the URL, which may be confusing to the user (or may even be suspicious to the user). You also aren't setting any values to those hidden inputs, unless you have something else not included here which does that?
Either way, your form will automatically include its inputs in the submitted request.

Passing data from view to controller action(httpget) to another view to same controller action (httppost)

I'm trying to enable posting Comments from the view where I display a Forum Post by id. That's the model which my view receives:
#model PostViewModel
the Model has and "Id" property, which I send to a controller with javascript:
<script>
$("#target").click(function () {
$("#formPlace").load('#Url.Action("AddComment","Posts", new { postId = Model.Id })');
});
</script>
That's the controller action I send the "postId" to:
[HttpGet]
public ActionResult AddComment(int postId)
{
var comment = new CommentViewModel();
comment.PostId = postId;
return this.PartialView("_AddComment", comment);
}
This view returns a form in which the user has to fill the comment's content:
#model MvcTemplate.Web.ViewModels.Posts.CommentViewModel
<div>
#using (Html.BeginForm("AddComment", "Posts", FormMethod.Post))
{
<div>Enter your comment here:</div>
<div>
#Html.TextAreaFor(x => Model.Content)
</div>
<input type="submit" name="Submit" />
}
</div>
When the view receives the model its "PostId" is still correct = what I set it with the javascript. However after the user submits the form, the CommentViewModel which is sent to the controller has 0(default int value) for "PostId". This is the controller action:
[HttpPost]
public ActionResult AddComment(CommentViewModel viewModel)
{
// transfer the view model to db model and save;
}
Any idea how I can keep the correct PostId?
When you submit the form to the AddComment action method, the default model binder will try to bind the form field values to the properties of your CommentViewModel object. Your form has an input field for the Content property, but you do not have one for the PostId. So the browser will send the value of only form element with name Content.
If you want PostId, You need to keep the Post id value in the form. Since user does not need to see/edit this, you may keep this in a hidden input field in the form.
You can use the Html.HiddenFor helper method to generate the hidden field with the name and value for the corresponding property.
#using (Html.BeginForm("AddComment", "Posts", FormMethod.Post))
{
<div>Enter your comment here:</div>
<div>
#Html.TextAreaFor(x => Model.Content)
</div>
#Html.HiddenFor(s=>s.PostId)
<input type="submit" name="Submit" />
}
Or just a hidden input element markup (the helper ultimately generate this only)
<input type="hidden" name="PostId" value="#Model.PostId" />
You need to put hidden field with PostId value in your form. You are only posting content. Alternatively your post action AddComment should have url parameter postId, so form's action url will include postId.
You can set your PostId in a TempData and can get in subsequent post action in controller. If you want to get it from view you need to set it in a hidden field as suggested by Shyju.

Update and ASP.NET MVC model on button click

I'm new to ASP.NET MVC. I'm trying to update model on button click with no success: every time I push the button an HttpGet controller method is invoked.
Here is my markup
#model DataInterface.Model.Entry
<button onclick="location.href='#Url.Action("Survey")'">Finish survey</button>
Here is Controller code
[HttpGet]
public ActionResult Survey()
{
var entry = new Entry();
return View(entry);
}
[HttpPost]
public ActionResult Survey(Entry newEntry)
{
// save newEntry to database
}
When I click button HttpGet method is invoked. Why?
It is bad to be a rookie)
Thanks to all!
If you access a URL without explicitly specifying the HTTP method, ASP.NET MVC will assume a GET request. To change this, you can add a form and send it:
#using (Html.BeginForm("Survey", "Controller", FormMethod.Post))
{
<input type="submit" value="Finish survey" />
}
If you do this, your POST method will be invoked. The Entry parameter, however, will be empty, since you do not specify any values to send along with the request. The easiest way to do so is by specifying input fields, e.g. text inputs, dropdown, checkboxes etc.
#using (Html.BeginForm("Survey", "Controller", FormMethod.Post))
{
#Html.TextBoxFor(m => m.Title)
<input type="submit" value="Finish survey" />
}
If you have the object stored on the server somewhere and only want to finish it off by writing it into the database or changing its status, you could pass the Id of the object (or some temporary Id) along the post request and make the controller method work only with the Id:
#using (Html.BeginForm("Survey", "Controller", FormMethod.Post))
{
#Html.HiddenFor(m => m.Id)
<input type="submit" value="Finish survey" />
}
[HttpPost]
public ActionResult Survey(Entry newEntry)
{
// newEntry.Id will be set here
}
#using (Html.BeginForm("Survey", "<ControllerName>", FormMethod.Post))
{
<input type="submit" value="Finish survey" />
}
you must declare your form
#model DataInterface.Model.Entry
#using (Html.BeginForm("action", "Controlleur", FormMethod.Post, new {#class = "form", id = "RequestForm" }))
{
<input type="submit" value="Finish survey" />
}

setting enctype = "multipart/form-data" causes all ViewBags value be lost

this is my View containing an upload file control. so it needs "multipart/form-data" content type.
#using (Html.BeginForm("Create", "RoutinTest", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div>
#Html.LabelFor(model => model.ScannedFile)
<div>
<input type="file" name="ScannedFile" multiple="multiple" />
#Html.ValidationMessageFor(model => model.ScannedFile)
</div>
</div>
<div>
<div>
<input type="submit" value="Save" />
</div>
</div>
this is my controller and it's Create action methods:
[HttpGet]
public ActionResult Create(string patientId, string fullName)
{
ViewBag.PatientId = patientId;
ViewBag.FullName = fullName;
return View();
}
[HttpPost]
public ActionResult Create() RoutinTest routintest, string patientId, string fullName)
{
}
The problem is that On second Create action method (post method) both patientId and fullName are lost. (patientId = 0 and fullName = null) but I set both of them on Get method.
Amazingly when I change the form content type to it's default (by removing multipart/form-data), I am able to have those two parameters values. I know I can solve the problem without changing the form content type, by setting those two ViewBags value to hidden fields but I just want to know why this happens? What affect the "multiPart/form-data" form content type has on those ViewBags values?
thanks
Remember that your patientId and fullName is found in the URL. Reassigning them to the ViewBag has nothing to do with it (remove the ViewBag and see what happens)
// Looks familliar? This is your first request.
Create?patientId=0&fullName=
The parameters is passed to the second Create action method by default because the URL parameters is maintained.
// By default, parameters are not cleared during the second request.
Create?patientId=0&fullName=
When you set enctype = "multipart/form-data", the URL parameters gets cleared, resulting in something like this.
Create
Which means that it is the parameters that are lost and not the ViewBag data.
Related Problem: Form Post with enctype = "multipart/form-data" causing parameters to not get passed

Why Ajax.BeginForm does not pass form values?

I'm trying to show a partial view via calling Ajax.BeginForm, but I can't receive the values of my form(I need to get the value of hidden input, bookId, in controller, e.g 5).
// View
#using (Ajax.BeginForm("Detail", "Books", new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "ShowBookDiv" }))
{
<input type="hidden" id="bookId" value="5" />
<input type="submit" id="sBtn" value="Details" />
}
// Controller
[HttpGet]
public ActionResult Detail(string bookId)
{
if (Request.IsAjaxRequest())
{
var a = Request["bookId"].ToString();
// some code to get details
return PartialView("ShowBooks", details);
}
...
}
When I trace the code in Controller bookId is null!
I've added the "name" property to hidden field and it works !!! really strange!
<input type="hidden" name="bookId" id="bookId" value="5" />
Ajax.BeginForm is a pain, IMO.
I would Use $.ajax from JQuery Ajax API :
http://api.jquery.com/jQuery.ajax
here is a good example for you to see how it works :
http://www.tugberkugurlu.com/archive/working-with-jquery-ajax-api-on-asp-net-mvc-3-0-power-of-json-jquery-and-asp-net-mvc-partial-views
Posting the whole form requires a little bit of work (in terms of validation, etc.) but you will have complete control over the action if you are good with JavaScript.

Resources