MVC Form Form element not going to controller action - asp.net-mvc

I think I must be doing something silly, but if anyone can point out what I'm doing wrong, that would be great!
I have a form in a Razor view like:
#using (Html.BeginForm("Index", "SiteKPIs", FormMethod.Get))
{
<table>
<tr>
<td style="margin-right: 25px;">Site</td>
<td>#Html.DropDownList("siteId", new SelectList(ViewBag.Sites, "SiteID", "SiteDisplayName"))</td>
</tr>
<tr>
<td>Range</td>
<td>
<select id="rangeId"><option value="0">test</option></select>
<input class="btn btn-primary btn-xs" type="submit" value="Go" />
</td>
</tr>
</table>
}
The signature of my controller action looks like:
public ActionResult Index(int? siteId, int? rangeId)
I get a value for siteId, but rangeId is null. What am I doing wrong?

If you want to use plain html select, then you need to set Name attribute of your select to expected param name in your Controller Action:
<select id="rangeId" name="rangeId"><option value="0">test</option></select>
But my suggestion is to use DropDownList helper either way.

I believe it would be better to use a HtmlHelper for a dropdownlist, like so:
<div class="form-group">
<label for="range">Range</label><br />
#Html.DropDownList("RangeID", null, "Please select...",
new { #class = "form-control", id = "rangeID" })
</div>
Then, inside your controller, you can populate the dropdownlist there, with something like:
List<SelectListItem> options = new List<SelectListItem>();
options.Add(new SelectListItem { Text = "Test", Value = "0"});
// and so on...
You can then use a ViewBag in your controller and make it equal to this list, like so:
ViewBag.RangeID = options;

Related

In a Razor View's #html.ActionLink, how do we pass the value of a dropdown list?

So what I am trying to do is that I have a database table of Roles, that I want to display in a dropdown list, and send the value to a different controller function. However, when I try to do this, I do not receive the value of the new Role that is selected from my dropdown list, but instead the value that was previously in my Model.
Here is my code for CSHTML:
#model IEnumerable<OnlineStoreData.Model.User>
<h4>List of Users: </h4>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.UserName)
</th>
<th></th>
</tr>
#foreach (var user in Model) {
if (user.Role.RoleName.TrimEnd(' ') == "User")
{
<tr>
<td>
#Html.DisplayFor(modelItem => user.UserName)
</td>
<td>
#Html.DropDownListFor(modelItem => user.Role.RoleName, new SelectList(ViewBag.RoleList)) //Here I need to select a new Role, for example "Admin"
#Html.ActionLink("Promote", "Promote", new { id = user.UserId, role = user.Role.RoleName }) |
#Html.ActionLink("Delete", "Delete", new { id = user.UserId })
</td>
</tr>
}
}
</table>
and this is the code for my Controller
public ActionResult ManageUsers()
{
ViewBag.RoleList = storeDBEntities.Roles.Select(role => role.RoleName).ToList();
return View(storeDBEntities.Users.ToList());
}
public ActionResult Promote(int id, string role)
{
//Here I should get the new role selected in the dropdown list, but I keep getting "User", which is the old role.
User toPromUser = storeDBEntities.Users.Find(id);
Role newRole = storeDBEntities.Roles.FirstOrDefault(r => r.RoleName == role);
if(toPromUser != null && newRole != null)
{
toPromUser.Role = newRole;
toPromUser.UserRole = newRole.RoleId;
storeDBEntities.SaveChanges();
}
return RedirectToAction("ManageUsers", "Users");
}
I am not sure how I should fix this to get the code to perform what is intended. Thank you.
The problem is, that you cannot dynamically append the selected value of your dropdown to your action link without JavaScript.
I think a more elegant approach would be to put your drop down and action buttons in a <form>. That way the method can also be a post, which is a bit more nice in a way, as get operations should not manipulate data.
<td>
<form method="post" action="#Url.Action("Promote", new { id = user.UserId })">
#Html.DropDownList("role", new SelectList(ViewBag.RoleList))
<button type="submit">Promote</button>
|
#Html.ActionLink("Delete", "Delete", new { id = user.UserId })
</form>
</td>
Note that the name of your drop down list should match the name of the role parameter of your controller.
When that works, you could then add the [HttpPost] attribute to your Promote action, to clarify that this method changes something.
For your delete action you could do something similar. Either make a second <form> with a different URL, or make it a submit button, too, in the same form, and give the buttons each a name and value.
The value of the button you clicked on will be sent to the server - note that I changed the form action URL:
<td>
<form method="post" action="#Url.Action("Update", new { id = user.UserId })">
#Html.DropDownList("role", new SelectList(ViewBag.RoleList))
<button type="submit" name="operation" value="promote">Promote</button>
|
<button type="submit" name="operation" value="delete">Delete</button>
</form>
</td>
And then decide what to do in the controller:
[HttpPost]
public ActionResult Update(int id, string operation, string role)
{
...
Lastly, you probably want a confirmation message on the delete action, which can be done so:
<button type="submit" name="operation" value="delete" onclick="return confirm('Do you really want to delete this user?');">Delete</button>

Data not loading on partial view, MVC

I am doing work on form where user can enter a customer record....View is scaffold with Create controller.
On 'Create' View, user can enter 'engineNo' to check its details which passes to another action "CheckRecord",,it can be seen from view...
<form>
<input type="text" id="enginNo" />
<input type="button" value="search" id="btnSearch" />
</form>
#using (Html.BeginForm("Index","Home",FormMethod.Get))
{
#Html.AntiForgeryToken()
<div id="info">
#{Html.RenderAction("CheckRecord","Sales");}
</div>
some create fields
}
The Create and "CheckRecord" actions are,,
public ActionResult Create()
{
ViewBag.CustomerId = new SelectList(db.CustomersDMs, "CustomerId", "Name");
ViewBag.SMClientBranchId = new SelectList(db.SMClientBranchesDMs, "SMClientId", "Name");
ViewBag.EngineNumber = new SelectList(db.StockDMs, "EngineNumber", "ChasisNumber");
return View();
}
public ActionResult CheckRecord(string enginNo)
{
var results = db.StockDMs.Where(c=>c.EngineNumber ==enginNo);
return PartialView("_part",results);
}
And my partialview,,,
#model IEnumerable<SM.CRM.AutosLoan.Models.Core.DomainModels.StockDM>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.AutoCompanyBrand.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.SMClientBranch.Name)
</td>
}
My problem is, the partial view is rendered correctly but the Model of partial view doesn't have value,,,Why is that, i am doing something wrong...Please help,,,Thanks for your time
(Posting this as answer since I mentioned it in comments and that's not the correct place)
Your action CheckRecord(string enginNo) takes an argument of enginNo, but you're calling it without any argument. That in turn means your db lookup will most likely not return any results, unless you get results on..
var results = db.StockDMs.Where(c => c.EngineNumber == null);
Make sure the action gets a valid argument, for example:
#{ Html.RenderAction("CheckRecord", "Sales", new { enginNo = "abc123" }); }

How to display labels and textboxes with the help of model properties in MVC5 razor view with html helpers?

I am not able to create labels and textboxes using model in my view with html helpers.
My View Syntax:
#using (Ajax.BeginForm("RoomsAvail",new AjaxOptions
{
UpdateTargetId = "RoomsAvailData",
InsertionMode ="InsertionMode.Replace"
}))
{
<input type='text' id="Checkin" class="form-control datepicker" />
<input type='text' id="Checkout" class="form-control datepicker" />
<button type="submit" value="Search"></button>
}
#model IEnumerable<RoomAvailabilitySummary>
<div>
#Html.LabelFor(model=>model.ARRDAT)
</div>
<div>
#Html.EditorFor(model=>model.Name)
</div>
My Model
public class RoomAvailabilitySummary
{
public string ARRDAT{get;set;}
public string Name{get;set;}
}
After doing like this, my view is not rendering the model properties into my view to display text for labels and getting the error as "Syste.Collection.Generic.IEnumerable does not contain the definiton for ARRDAT"
Why i am not able to render model property in my html helper to display the name with the help of html helper?
And also i want to access my model values in controller. How can i do this?
Your model is:
#model IEnumerable<RoomAvailabilitySummary>
And you trying to access Name in IEnumerable:
<div>
#Html.EditorFor(model=>model.Name)
</div>
You should use foreach if it is IEnumerable OR just #model RoomAvailabilitySummary if it is not IEnumerable
Added:
Something like this should work:
#model IEnumerable<RoomAvailabilitySummary>
#if(Model.Count() > 0)
{
<div>
#Html.LabelFor(model=>Model.First().Name)
</div>
}
#foreach (var item in Model)
{
<div>
#Html.EditorFor(model=>item.Name)
</div>
}
I think u are trying to iterate over the model (list):
#model IEnumerable<RoomAvailabilitySummary>
#Html.LabelFor(model => model[0].Name)
#foreach(var room in Model)
{
<br />
#Html.EditorFor(x => room.Name)
}

How do I return List or Collection to Controller from View in MVC 3?

Someone please help me return this list properly from my view. I don't see why I'm returning null for my fieldModelList I try to pass to the controller...
Here is my view:
#model List<Regions.SOA.UI.CopyBookSchemaCreator.Models.FieldModel>
<script type="text/javascript" src="~/Scripts/jquery-ui-1.8.11.min.js"></script>
#using (Html.BeginForm("GetResponse", "TestMethods", FormMethod.Post))
{
<table id="tblMethods">
<tr>
<th>
Property Name
</th>
<th>
Request
</th>
</tr>
#foreach (FieldModel fieldModel in Model)
{
<tr>
<td>
#Html.DisplayFor(m => fieldModel.PropertyName)
</td>
<td>
#Html.TextBoxFor(m => fieldModel.PropertyValue)
</td>
</tr>
}
</table>
<div>
<input type="submit"/>
</div>
and here is my controller:
[HttpPost]
public ActionResult GetResponse(List<FieldModel> fieldModelList)
{
return GetResponse(fieldModelList);
}
I am hitting the HttpPost method but if I place a breakpoint just inside it, I am returning null for the fieldModelList right off the bat, which I was hoping would be a list of the values I entered into the texboxes on the view that is of model FieldModel...
I think something is wrong with my logic versus my syntax, or as maybe as well as my syntax, but basically what I want to do is return back a list of type FieldModel with each corresponding PropertyName and PropertyValue to the controller. I noticed I am not passing any kind of id parameter in my BeginForm statement in the view. Do I need one here?
Just in case, here is my model class for FieldModel:
namespace Regions.SOA.UI.CopyBookSchemaCreator.Models
{
public class FieldModel
{
[Display(Name = "Property")]
public string PropertyName { get; set; }
[Display(Name = "Value")]
public string PropertyValue { get; set; }
}
}
Phil Haack wrote an article some time ago explaining how to bind collections (ICollection) to view models. It goes into additional detail about creating an editor template, which you could certainly do as well.
Basically, you need to prefix the HTML elements' name attributes with an index.
<input type="text" name="[0].PropertyName" value="Curious George" />
<input type="text" name="[0].PropertyValue" value="H.A. Rey" />
<input type="text" name="[1].PropertyName" value="Ender's Game" />
<input type="text" name="[1].PropertyValue" value="Orson Scott Card" />
Then, your controller could bind the collection of FieldModel
[HttpPost]
public ActionResult GetResponse(List<FieldModel> fieldModelList)
{
return GetResponse(fieldModelList);
}
I'm not 100% sure the following would name the attributes correctly (I'd recommend using the editor template) but you could easily use the htmlAttributes argument and give it a name using the index.
#for(int i = 0;i < Model.Count;i++)
{
<tr>
<td>
#Html.DisplayFor(m => m[i].PropertyName)
</td>
<td>
#Html.TextBoxFor(m => m[i].PropertyValue)
</td>
</tr>
}
Editor Template
If you wanted to go as far as adding an editor template, add a partial view named FieldModel.ascx to /Views/Shared that is strongly typed to a FieldModel
#model Regions.SOA.UI.CopyBookSchemaCreator.Models.FieldModel
#Html.TextBoxFor(m => m.PropertyName) #* This might be a label? *#
#Html.TextBoxFor(m => m.PropertyValue)
And, then the part of your view responsible for rendering the collection would look like:
#for (int i = 0; i < Model.Count; i++) {
#Html.EditorFor(m => m[i]);
}

Asp.MVC RenderAction for part of the page doesn't work as I expect

Ok I mess my page really bad and I need good help here.
I have a login page with Login and Register partial views.
RegisterView has it's own ViewModel class and it makes me problem.
I render Register partial view by using "RenderAction" helper.
Biggest problem is validation. When I don't enter anything in register fields and click submit register partial view is not updated inside it's parrent LoginView but return me only RegisterView. In other words my validation works but not where I want it to work.
LogOn.cshtml (this one contains register partial view)
<div id="regstrationForm">
#{Html.RenderAction("RegisterUser", "Account");}
</div>
Register (Partial View)
#using (#Ajax.BeginForm("RegisterUser", "Account", new AjaxOptions { UpdateTargetId = "reg" }))
{
<table id="reg">
...
<tr>
<td>
#Html.TextBoxFor(u => u.Username, new { #class = "registrationTextFields", placeholder = "Email" })
</td>
</tr>
<tr>
<td>
#Html.TextBoxFor(p => p.Password, new { #class = "registrationTextFields", placeholder = "Password" })
</td>
</tr>
<tr>
<td align="right">
<input class="signUpButton" type="submit" value="Sign up" />
</td>
</tr>
<tr>
<td>
#Html.ValidationMessage("myerrorsummary")
</td>
</tr>
</table>
This is HttpPost controller method when user click on sign up button.
Here I tried to return "PartialView()" and it turns my input fields to red css style but not display validation information bellow those fields.
[HttpPost]
public ActionResult RegisterUser(RegisterViewModel logOnViewModel)
{
if (ModelState.IsValid)
{
MembershipCreateStatus result;
try
{
...
}
else
{
ModelState.AddModelError("myerrorsummary", "The input is not valid");
ViewBag.CountryList = countryRepository.GetAllCountries();
ViewBag.CityList = cityRepository.GetAllCitiesByCountryId(1);
return View(logOnViewModel);
}
}
I suspect that you forgot to include the following script in your main view:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
This is what makes Html helpers such as Ajax.BeginForm and Ajax.ActionLink to perform AJAX requests instead of normal.
You might also take a look at the following article which explains in more details about how those helpers work in ASP.NET MVC 3.

Resources