Passing route values to Html.BeginForm - asp.net-mvc

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.

Related

MVC get data from dynamic field

I'm very new in MVC :(
I created a dynamic form by cloning a principal DIV element and its elements. The elements are combobox, textbox and a date textbox. When I create a new "clone", the DIV every member of itself has an incremental ID like tab_Container, tab_Container_1, text, text1, combo, combo1, etc... Now, I'm trying to get the values of each member in the Divs into the controller.
Googling I find something like this:
[HttpPost]
public ActionResult NewEntry(Model Entry)
{
Control myControl = new Control();
myControl.FindControl("Text0");
if (myControl != null)
{
/// apparently, find the control,here i wanna to get the value of each field !! ¿?
/// do i have to create a list[] ... exist something like Entry.Text0 = myControl.value?
}
else
{
Response.Write("Control not found");
}
return View(Entry);
}
Any suggestion? Is Control the best option? Do I have to do something else in Javascript code?
While it's normally better to have some sort of Model / ViewModel this situation is a bit different. MVC binds on the "Name" property of your form inputs.
So say for instance your razor syntax generates something like this:
<form>
<input type="text" name="input1" />
<input type="text" name="input2" />
<!-- etc etc etc -->
<input type="submit" value="submit" />
</form>
since this is dynamically generated and you don't have a model that would cleanly bind to this. You can use the FormCollection type as the parameter of your action. This gives you a collection of all items posted to the server that you could then loop through or peer into to get the properties that you want.
public ActionResult myAction(FormCollection collection)
{
var value = collection["input1"];
var value2 = collection["input2"];
return View();
}

ASP.NET MVC - why ViewBag prop return "value" string instead of actual value?

I need to pass some flag into a view and get it back.
But requirements are:
this flag is not part of model
and it must not be stored in session or such.
I mean - flag visibility scope should be - current page for current user only.
I tried to put it into a ViewBag like this:
public ActionResult Product_Add()
{
ViewBag.IsNew = true;
ViewData["IsNew"] = ViewBag.IsNew;
ViewBag.RecordActionName = "Add";
return View("Product_Edit");
}
And then use this code in *.cshtml:
<input type="hidden" name="IsNew1" value="#ViewBag.IsNew" />
<input type="hidden" name="IsNew2" value='#ViewData["IsNew"]' />
But in resulting HTML I see this:
<input type="hidden" name="IsNew1" value="value" />
<input type="hidden" name="IsNew2" value='value' />
Then I tried this code in *.cshtml:
#{ string isNewRec = ViewBag.IsNew.ToString(); }
<input type="hidden" name="IsNew1" value="#isNewRec" />
And now it works:
<input type="hidden" name="IsNew1" value="True" />
Question is - why first attempt put "value" text instead of boolean value into HTML?
Also the strange thing - this code works fine:
<input type="hidden" name="ProductID" value="#ViewBag.ProductID" />
So, for integer values in ViewBug it works, returns an actual interger value, but for boolean it returns "value" text.
Another part of question.
Currently I use code like this:
[HttpPost]
public ActionResult Product_Commit(Product pProduct)
{
if (ModelState.IsValid)
{
AbcProducts ctx = new AbcProducts();
bool isNew = Convert.ToBoolean(Request.Form["IsNew"]);
if (isNew)
ctx.Products.Add(pProduct);
else
{
// [...]
}
ctx.SaveChanges();
}
return View();
}
Could you recommend something more correct from MVC point of view to pass non-model parameter into a view and get it back then with submited data?
But this parameter should not be stored anywhere where other pages can see it somehow.

How to send a model property value from a view to controller

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]

ViewData not being posted back to Controller

I have two pages, one that edits user information, and one that edits information in a pictures table. I recently stopped using strongly typed viewmodels due to the varying types of data required on each page.
The page that edits the user information works fine, but the page that edits picture information does not post back any of the edits that are made in the input fields; except for the ID, which is correct, all the other values come back as null. They both seem to be structured exactly the same way -- I can't figure out what's the difference. As far as I can tell the code for both pages are the same, but I'm not getting data back on the second one.
User Controller and View which works
Controller
public ActionResult Preferences()
{
int userid = getUserID(User.Identity.Name);
// Info for user preferences
var accountInfo = db.users.Single(l => l.ID == userid);
ViewData["accountInfo"] = accountInfo;
AccountController usr = new AccountController(); // Info for user menu
ViewData["userInfo"] = usr.getUserInfo(User.Identity.Name);
return View();
}
[HttpPost]
public ActionResult Preferences(user accountInfo, string oldPW)
{
// Do stuff to save user info
return RedirectToAction(actionname, routeValues);
}
View
#using (Html.BeginForm("Preferences", null, FormMethod.Post,
new { id = "prefsform" }))
{
AutoShowApp_MVC.user item = new AutoShowApp_MVC.user();
item = ViewBag.accountInfo;
<input id="lastname" name="lastname" type="text" value="#item.lastname"/>
<input id="address1" name="address1" type="text" value="#item.address1"/>
<input id="city" name="city" type="text" value="#item.city"/>
<input id="state" name="state" type="text" value="#item.state"/>
<input type="submit" value="Submit Changes" />
}
Picture Controller and View which DON'T work
Controller:
public ActionResult Edit(long id)
{
var picInfo = db.lmit_pics.Single(l => l.ID == id);
ViewData["picInfo"] = picInfo; // get Picture Info
// Get User Info for menu
AccountController usr = new AccountController();
ViewData["userInfo"] = usr.getUserInfo(User.Identity.Name);
return View();
}
[HttpPost]
public ActionResult Edit(lmit_pics picInfo)
{
// Do stuff to save picInfo
return RedirectToAction("Index");
}
View:
#using (Html.BeginForm("Edit", null, FormMethod.Post, new { id = "editform" }))
{
AutoShowApp_MVC.lmit_pics item = new AutoShowApp_MVC.lmit_pics();
item = ViewBag.picInfo;
<input type="text" id="model" value="#item.model" />
<input type="text" id="description" value="#item.description" />
<input type="submit" value="Save" />
}
You do not have the name attribute specified on the inputs on your picture editing form.
<input type="text" id="model" value="#item.model" />
Should Be
<input type="text" id="model" name="model" value="#item.model" />
The form collection works from the name attribute, not the Id attribute which is why you are not getting any data back (you are, it is just not properly attributed).
However, I agree with Wahid above, using strongly typed view models, editorFor helpers, etc not only help to prevent issues such as the above, but really go a long way in making a more secure, easier to maintain site.

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