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" }); }
Related
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>
I have posted the relevant code to this issue below. My problem is, let's say, the database is displaying NA, I want to edit it and put in 1.1, or some number. Instead of updating and saving this new number, it deletes NA and does not update or save anything, so I know it is doing something, but I'm not sure where I have gone wrong. If I change the type in the model to int or object, it gives an error for conversion to string. Can someone help please? Thank you!
Controller:
public ActionResult Edit ()
{
return View ();
}
[HttpPost]
public ActionResult Edit(MyIssue issues)
{
var model = new Test.Models.Tables();
if (ModelState.IsValid)
{
db.Entry(issues).State = EntityState.Modified;
issues.Number = model.Number;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(issues);
}
Model:
namespace Test.Models
{
public class Tables: DbContext
{
public string Number { get; set; }
}
}
View:
<td>
#if (issue.Number != null)
{
#Html.HiddenFor(modelItem => issue.Number)
#Html.DisplayFor(modelItem => issue.Number)
<text>|</text>
<h5 id="editclass">
#Html.ActionLink("Edit", "Page1", new { id = issue.Number })
</h5>
using (Html.BeginForm())
{
#Html.ValidationSummary(true) {
<fieldset>
#Html.HiddenFor(modelItem => issue.Number)
<div class="editor-field">
#Html.EditorFor(modelItem => issue.Number)
#Html.ValidationMessageFor(modelItem => issue.Number)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
}
}
</td>
From your code, I assume that the code you shown is inside a loop where issue is the loop iterator variable. So razor will generate an input field with name "issue.Number". When the form is submitted, model binder cannot bind this form value to the Number property of your MyIssue object ! So it gets the default null value and your code is assigning the null value as the Number property and saving it.
You should generate an input field with name="Number". You may use the Html.TextBox helper method to do so.
#foreach (var issue in SomeCollection)
{
<tr>
<td>
#using (Html.BeginForm())
{
<!-- Other fields also goes here -->
#Html.TextBox("Number",issue.Number)
<input type="submit" />
}
</td>
</tr>
}
I created a list based on the scaffolding
#model IEnumerable<FleetLink.Domain.Entities.UserTable>
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
<table>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Master_IP)
#Html.TextBoxFor(modelItem=>item.Master_IP)
</td>
<td>
#Html.DisplayFor(modelItem => item.Master_Name)
</td>
</tr>
<tr><td><input type="submit" value="Submit" /></td></tr>
</table>
}
In my controller I have a get and a post method for index
[HttpPost]
public ActionResult Index(List<UserTable> list)
{
return View();
}
[HttpGet]
public ActionResult Index()
{
var users= from userTable in _repo.GetUsers()
select userTable;
return View(users);
}
I was expecting it would call post method when I clicked on submit and would pass the entire tables data to the Index HTTPPost method. But it is always calling the get method of Index. The goal is to pass entire table data after user edits it so I can save all table data at once. Please advice on what I am doing wrong.
I resolved this issue by changing the foreach to for(int i=0....) as well as changing the #using (Html.BeginForm("Index", "Home", FormMethod.Post)) to
#using (Html.BeginForm(FormMethod.Post))
Thanks
I have a PartialView that is an image upload, and basically I am displaying some images and then the normal Upload buttons :-
#model MvcCommons.ViewModels.ImageModel
<table>
#if (Model != null)
{
foreach (var item in Model)
{
<tr>
<td>
<img src= "#Url.Content("/Uploads/" + item.FileName)" />
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
</tr>
}
}
</table>
#using (Html.BeginForm("Save", "File", FormMethod.Post, new { enctype = "multipart/form-data" })) {
<input type="file" name="file" />
<input type="submit" value="submit" /> <br />
<input type="text" name="description" />
}
Now my idea is to have this in different pages. I tried it in 1 page already and is working fine, however when I Upload an image,
public ActionResult ImageUpload()
{
ImageModel model = new ImageModel();
model.Populate();
return View(model);
}
I want to go back to the "previous" View, ie the View that is hosting this partial view? When I do return View(model) as above, I get into the ImageUpload partial view which I do not want to.
Thanks for your help and time.
***UPDATE*********
I went for the simple route for the time being, and hard coded the actual View name
public ActionResult ImageUpload()
{
ImageModel model = new ImageModel();
model.Populate();
return View("~/Views/Project/Create.cshtml", model);
}
however I got an error :-
The model item passed into the dictionary is of type MvcCommons.ViewModels.ImageModel, but this dictionary requires a model item of type MvcCommons.Models.Project.
Use the overload that takes a string of the name of the view you want.
http://msdn.microsoft.com/en-us/library/dd460310
protected internal ViewResult View(
string viewName,
Object model
)
i.e.
return View("ViewName", model);
if you have this in different pages then you can inject context via the action paramaters;
public ActionResult ImageUpload(string parentViewName)
{
ImageModel model = new ImageModel();
model.Populate();
return View(parentViewName, model);
}
NOTE: You should only need to pass the views name not the path:
return View("Create", model);
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]);
}