I have a DropDownListFor that is on my Index page and one in my Create page. Both dropdownlists serve the same purpose.
What I want is when the user selects an item in the Index dropdownlist in the index page, it saves that selected item's value which is a GUID to the session and when the Create page loads, I want the dropdownlist in there to select the item based on the GUID in the session.
At the moment when the user clicks on "Create" and goes to the create page, I am merely setting up an object and sending that object to the Create View.
Edit:
I am sending the user over to the Create page by doing this:
Html.ActionLink("Create New Listing", "Create", null, new { #class = "btn btn-primary" }))
How do I send the GUID of the selecteditem over to the view?
I guess you have a situation like this. Here is the Index view:
#model Models.IndexViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm("SaveGuid", "Flow"))
{
Html.DropDownListFor(x => x.SelectedGuid, Model.Guids, new { onchange = "this.form.submit();" });
}
Here is the Index model:
public class IndexViewModel
{
public Guid SelectedGuid { get; set; }
public SelectList Guids { get; set; }
}
The Index and SaveGuid Action look like this:
private List<Guid> Guids = new List<Guid> { Guid.NewGuid(), Guid.NewGuid() }; // for testing only
public ActionResult Index()
{
var model = new IndexViewModel { Guids = new SelectList(Guids, Guids.First()) };
return View(model);
}
public ActionResult SaveGuid(IndexViewModel model)
{
Session["SelectedGuid"] = model.SelectedGuid;
return new RedirectResult("Create");
}
The Create View looks like this...
#model MvcBootStrapApp.Models.CreateViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm("SaveGuid", "Flow"))
{
#Html.DropDownListFor(x => x.SelectedGuid, Model.Guids, new { onchange = "this.form.submit();" });
}
#using (Html.BeginForm("SaveCreate", "Flow"))
{
// setup other controls
<input type="submit" value="Submit" />
}
Using a CreateViewModel like this...
public class CreateViewModel
{
public Guid SelectedGuid { get; set; }
public SelectList Guids { get; set; }
// include other model properties
}
The Create and CreateSave ActionResults look like this...
public ActionResult Create()
{
Guid selectedGuid = Guids.First();
if (Session["SelectedGuid"] != null)
selectedGuid = (Guid)Session["SelectedGuid"];
return View(new CreateViewModel
{
Guids = new SelectList(Guids, selectedGuid),
SelectedGuid = selectedGuid
});
}
public ActionResult SaveCreate(CreateViewModel model)
{
// save properties
return new RedirectResult("Index");
}
I used two forms to allow both the change of selected Guid and to postback all the Create properties.
If you want to use Session, what I think you need is to use a form to post to an ActionResult to save the dropdownlist's value and then redirect to the Create page.
public ActionResult SaveGuid(Guid value)
{
Session["SelectedGuid"] = value;
return new RedirectResult("Create");
}
Then in your Create ActionResult, pass the Session value to the Create View's Model.
public ActionResult Create()
{
var selectedGuid = (Guid)Session["SelectedGuid"];
return View(new CreateViewModel { SelectedGuid = selectedGuid, /* include other properties */ };
}
In your view you can set the selected option on the SelectList passed to your DropDownListFor...
#Html.DropDownListFor(
x => x.SelectedGuid,
new SelectList(Model.ListOfStuff, "Key", "Value", Model.SelectedGuid)
)
Related
I am trying to pull the data from a table stored in SQL 2008 into my MVC4
In My Controller :
public ActionResult Test()
{
SurveyEntities survey = new SurveyEntities();
var doctorList = survey.Doctors.ToList();
return View(doctorList);
}
and in my View:
#model IEnumerable<Survey.DataAccess.Doctor>
#{
ViewBag.Title = "Test";
}
<h2>Test</h2>
#using (Html.BeginForm("Test", "Home", FormMethod.Post))
{
#Html.DropDownListFor(m => m.)
}
But I am not able to access the field name in m, say for eg., the doctor's name, to bind it to the dropdownlist.
Where am i going wrong ?
If you dont need to bind to the result value you can also use Html.DropDownList('name', new SelectList(Model)) If you have to use DropDownListFor you would have to change your model and add a property to bind the select result like Html.DropDownListFor(m=>m.DoctorId, new SelectList(Model.Doctors).....
Normally, you want to use ViewModel, so that you can retrieve the selected doctorId when the form is posted back to server.
For example,
Model
public class SurveyModel
{
public string SelectedDoctorId { get; set; }
public IList<SelectListItem> AvailableDoctors { get; set; }
public SurveyModel()
{
AvailableDoctors = new List<SelectListItem>();
}
}
View
#model DemoMvc.Models.SurveyModel
#using (Html.BeginForm("Index", "Home"))
{
#Html.DropDownListFor(m => m.SelectedDoctorId, Model.AvailableDoctors)
<input type="submit" value="Submit" />
}
Controller
public ActionResult Index()
{
var model = new SurveyModel
{
AvailableDoctors = GetDoctorListItems()
};
return View(model);
}
[HttpPost]
public ActionResult Index(SurveyModel model)
{
if (ModelState.IsValid)
{
var doctorId = model.SelectedDoctorId;
// Do something
return View("Success");
}
// If we got this far, something failed, redisplay form
// Fill AvailableDoctors again; otherwise, DropDownList will be blank.
model.AvailableDoctors = GetDoctorListItems();
return View(model);
}
private IList<SelectListItem> GetDoctorListItems()
{
/*
SurveyEntities survey = new SurveyEntities();
return survey.Doctors
.Select(d => new SelectListItem {Text = d, Value = d.ToString()})
.ToList();
*/
// Simulate doctors return from database.
return new List<SelectListItem>
{
new SelectListItem {Text = "John Doe", Value = "1"},
new SelectListItem {Text = "Eric Newton", Value = "2"}
};
}
you can put this code in the Test method:
> ViewData["doctors"] = new SelectList(doctorList,"value", "text");
and then in a view:
#using (Html.BeginForm("Test", "Home", FormMethod.Post))
{
#Html.DropDownList("name", ViewData["doctors"] as SelectList)
input type="submit" value="Submit" />
}
I have the Action method and the View for editing properties of some items.
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public async Task<ActionResult> Edit(Item item)
{
if (ModelState.IsValid)
{
db.Entry(item).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.CatagorieId = new SelectList(db.Catagories, "ID", "Name", item.CatagorieId);
return View(item);
}
and
#model OpenOrderFramework.Models.Item
#using OpenOrderFramework.Extensions
#{
ViewBag.Title = "edit";
}
<h2>Editing</h2>
#using (Html.BeginForm())
{
<div class="form-horizontal">
<h4>The car</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.ID)
<-- etc -->
But when I submit the form I get an error
Store update, insert, or delete statement affected an unexpected number of rows (0).
I figured out that in action method ID of the item that was posted is always 0 even if real ID of the item is different.
Why does it happen?
GET Action method:
// GET: Items/Edit/5
[Authorize(Roles = "Admin")]
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Item item = await db.Items.FindAsync(id);
if (item == null)
{
return HttpNotFound();
}
ViewBag.CatagorieId = new SelectList(db.Catagories, "ID", "Name", item.CatagorieId);
return View(item);
}
When you post the form, the http call to your HttpPost action method is a totally separate Http request and Entity framework cannot track that entity.
As Darin mentioned in the comment, It is not a good idea to mix the entity classes in your UI layer. That makes it very tightly coupled.
What you should be using is creating and using a view model for your view. View model's are simply POCO classes, which is specific to the view.
public class ItemViewModel
{
public int Id {set;get;}
public string Name {set;get;}
public List<SelectListItem> Categories { set;get;}
public int SelectedCategory {set;get;}
}
And in your GET action, read the entity from your database,create an object of the view model and set the property values to that
public ActionResult Edit(int id)
{
var vm=new ItemViewModel { Id=id };
var item = db.Items.FirstOrDefault(s=>s.Id==id);
if(item!=null)
{
vm.Name = item.Name;
}
vm.Categories =db.Categories.Select(s=> new SelectListItem { Value=s.Id.ToString(),
Text=s.Name
}).ToList();
return View(vm);
}
And your view will be strongly typed to your view model
#model ItemViewModel
#using(Html.BeginForm())
{
#Html.DropdDownListFor(s=>s.SelectedCategory,Model.Categories,"Select")
#Html.HiddenFor(s=>s.Id)
#Html.TextBoxFor(s=>s.Name)
<input type="submit" />
}
And in your HttpPost action, read the existing entity from your db and update the property values you want to update.
[HttpPost]
public ActionResult Edit(ItemViewModel model)
{
if(ModelState.IsValid)
{
var item = d.Items.FirstOrDefault(s=>s.Id==model.Id);
item.Name = model.Name;
db.Entry(item).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
model.Categories =db.Categories.Select(s=>
new SelectListItem {
Value=s.Id.ToString(),
Text=s.Name }).ToList();
return View(model);
}
Make sure to add enough NULL checkings before accessing the entities/ objects in the code.
I am trying to create a dropdonw in my MVC web application.
Model
namespace projectname.Models
{
public class DropDownModel
{
public int id{get; set;}
puclic string value {get; set;}
}
}
Controller
using projectname.Models;
{
public class DropDownController: Controller
{
public ActionResult Index() //where Index is one of the view
{
List <SelectListItem> listItem = new List<SelectListItem>();
DropDownModel drop = new DropDownModel();
drop.id = 1;
drop.value = "First";
listItem.Add(new SelectListItem() {Value = drop.Value, Text = drop.id.toString()});
return view(listitem);
}
}
}
View
#{
ViewBag.Title = "Home Page";
}
<h2>#ViewBag.Message</h2>
<p>
To learn more about ASP.NET MVC visit http://asp.net/mvc.
</p>
However, the drop down is not being displayed on my Index view.
I would suggest reading more about MVC. You have nothing rendering the dropdown on your view and you have a model that more or less does the same-thing your listitem is doing. This could be handled by one object instead of two. That said :
Controller
public class HomeController : Controller
{
public ActionResult Index()
{
List<SelectListItem> listItem = new List<SelectListItem>();
DropDownModel drop = new DropDownModel();
drop.id = 1;
drop.value = "First";
listItem.Add(new SelectListItem() { Value = drop.id.ToString(), Text = drop.value });
return View(listItem);
}
}
View
Note the #Model List at the top of the view. This defines the strongly typed model asigned to the view. This Model is passed from the controller (listitem) to the view.
#model List<SelectListItem>
#{
ViewBag.Title = "title";
}
#Html.DropDownList("name", Model)
<h2>title</h2>
There are a few ways of display DropDownList in MVC. Here is my way.
Note: You need a collection of SelectListItem in model.
Model
public class MyModel
{
public int SelectedId { get; set; }
public IList<SelectListItem> AllItems { get; set; }
public MyModel()
{
AllItems = new List<SelectListItem>();
}
}
Controller
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyModel();
model.AllItems = new List<SelectListItem>
{
new SelectListItem { Text = "One", Value = "1"},
new SelectListItem { Text = "Two", Value = "2"},
new SelectListItem { Text = "Three", Value = "3"}
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyModel model)
{
// Get the selected value
int id = model.SelectedId;
return View();
}
}
View
#model DemoMvc.Controllers.MyModel
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#Html.DropDownListFor(x => x.SelectedId, Model.AllItems)
<input type="submit" value="Submit" />
}
You need to give your View the Model which is the listItem.
return View(listItem);
I've just started a new MVC project and I'm having trouble getting the post result from a form.
This is my Model Class :
public class User
{
public int id { get; set; }
public string name { get; set; }
}
public class TestModel
{
public List<User> users { get; set; }
public User user { get; set; }
public SelectList listSelection { get; set; }
public TestModel()
{
users = new List<User>()
{
new User() {id = 0, name = "Steven"},
new User() {id = 1, name = "Ian"},
new User() {id = 2, name = "Rich"}
};
listSelection = new SelectList(users, "name", "name");
}
}
This is my view class
#model MvcTestApplicaiton.Models.TestModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.DropDownListFor(x => x.user, #Model.listSelection)
<p>
<input type="submit" value="Submit" />
</p>
}
#if (#Model.user != null)
{
<p>#Model.user.name</p>
}
And this is my controller :
public class TestModelController : Controller
{
public TestModel model;
//
// GET: /TestModel/
public ActionResult Index()
{
if(model ==null)
model = new TestModel();
return View(model);
}
[HttpPost]
public ActionResult Test(TestModel test)
{
model.user = test.user;
return RedirectToAction("index", "TestModel");
}
}
The drop down list appears just fine but I can't see to get the ActionResult Test function to run. I thought it would just bind itself with reflection but whatever is wrong, I can't see it.
You have two main errors in your code.
As Brett said you're posting to the Index method, but you don't have Index method that supports POST verb. The easiest way to fix is to change Html.BeginForm() with Html.BeginForm("Test", "TestModel")
You're using Html.DropDownListFor in a wrong way. You could pass only a value types there, because don't forget that the View will generate an HTML page. So instead of User in your Model you should have an UserID and in your View you should have #Html.DropDownListFor(x => x.UserID, #Model.listSelection). And finally in your Action you should query your data source to get the details for the user with this ID.
Hope this helps.
Looks like you're posting back to index. Either use a GET Test() action method, or specify the ACTION parameter in BeginForm().
For example,
#using (Html.BeginForm("Test", "TestModel"))
{
#Html.DropDownListFor(x => x.user, #Model.listSelection)
<p>
<input type="submit" value="Submit" />
</p>
}
Or use a view named Test (rename index.cshtml to test.cshtml):
public ActionResult Test()
{
if(model ==null)
model = new TestModel();
return View(model);
}
I have View Model List like this:
public class PersonViewModel
{
int PersonId
bool LikesIceCream
}
The View will display a list of people and their preference to ice cream - like it or don't.
I'm not sure how to construct the html in a way that I can use the RadioButtonFor HTML helper and properly pass the values back to the controller. Simply creating RadioButtonFor's in a foreach loop doesn't help because they will have the same name. Any idea how I can hook these values up with the model binder?
Thanks.
View model:
public class PersonViewModel
{
public int PersonId { get; set; }
public bool LikesIceCream { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new[]
{
new PersonViewModel { PersonId = 1, LikesIceCream = true },
new PersonViewModel { PersonId = 2, LikesIceCream = false },
new PersonViewModel { PersonId = 3, LikesIceCream = true },
};
return View(model);
}
[HttpPost]
public ActionResult Index(IEnumerable<PersonViewModel> model)
{
// you will get what you need here inside the model
return View(model);
}
}
View (~/Views/Home/Index.cshtml):
#model IEnumerable<PersonViewModel>
#using (Html.BeginForm())
{
#Html.EditorForModel()
<input type="submit" value="OK" />
}
Editor template (~/Views/Home/EditorTemplates/PersonViewModel.cshtml):
#model PersonViewModel
<div>
#Html.HiddenFor(x => x.PersonId)
#Html.RadioButtonFor(x => x.LikesIceCream, "true") Yes
#Html.RadioButtonFor(x => x.LikesIceCream, "false") No
</div>