I am trying to use Html.DropDownListFor to build a dropdown list and get the user selected value. I can get the list to display but cannot figure out how to get the link to pass the selected value.
I have the following model:
public partial class ProductVariant
{
public int ID { get; set; }
public string Sku { get; set; }
}
The following ViewModel:
public class SkuToDiscountViewModel
{
public int ID { get; set; }
public string Sku { get; set; }
public IEnumerable<ProductVariant> Products { get; set; }
}
The following Controller action:
public ViewResult Index()
{
SkuToDiscountViewModel sModel = new SkuToDiscountViewModel();
List<ProductVariant> prodSkus = db.ProductVariants.ToList();
sModel.Products = prodSkus;
return View(sModel);
}
The following view:
#model mySpace.ViewModel.SkuToDiscountViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using(Html.BeginForm())
{
Html.DropDownListFor(x=>x.ID,
new SelectList(Model.Products,"ID", "Sku", Model.ID), " select ")
<p>
#Html.ActionLink("Edit", "Edit")
</p>
}
Any help is appreciated.
You need to a submit button to your form:
#model mySpace.ViewModel.SkuToDiscountViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using(Html.BeginForm())
{
Html.DropDownListFor(x=>x.ID,
new SelectList(Model.Products,"ID", "Sku", Model.ID), " select ")
<p>
<input type="submit" value="Save" />
</p>
}
Then you need to add an Action to your controller like this:
[HttpPost]
public ActionResult Index(SkuToDiscountViewModel postedModel)
{
// postedModel.ID will contain the value selected in the drop down list
}
Related
1) How to pass id in AddBookInCategory form in #Html.EditorFor(model=>model.CategoryID).
2) And second how after adding new item in public ActionResult AddBookInCategory(Books book) return to category with id it must be something like return RedirectToAction("ShowBooksFromCategory", 1); but it does not work.
HomeController:
public class HomeController : Controller
{
//
// GET: /Home/
TEntities TE = new TEntities();
public ActionResult Index()
{
return View();
}
public ActionResult ShowCategories()
{
return View(TE.Category.ToList());
}
public ActionResult ShowBooksFromCategory(int id)
{
return View(TE.Books.Where(key => key.CategoryID == id).ToList());
}
public ActionResult AddBookInCategory(int id)
{
return View();
}
[HttpPost]
public ActionResult AddBookInCategory(Books book)
{
TE.Books.Add(book);
TE.SaveChanges();
return View();
//return RedirectToAction("ShowBooksFromCategory", 1);
}
}
AddBookInCategory.cshtml:
#model TestDataBase.Models.Books
#{
ViewBag.Title = "AddBookInCategory";
}
<h2>AddBookInCategory</h2>
#using(#Html.BeginForm())
{
<p>Book Name:</p>
<br />
#Html.EditorFor(model=>model.BookName)
<p>Category:</p>
<br />
#Html.EditorFor(model=>model.CategoryID)
<input type="submit" value="Create"/>
}
Index.cshtml
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Html.ActionLink("ShowCategories", "ShowCategories")
ShowBooksFromCategory.cshtml
#model IEnumerable<TestDataBase.Models.Books>
#{
ViewBag.Title = "ShowBooksFromCategory";
}
<h2>ShowBooksFromCategory</h2>
<table>
#foreach(var item in Model)
{
<tr>
<td>
#item.BookName
</td>
</tr>
}
</table>
#Html.ActionLink("Add item", "AddBookInCategory", new {id=Model.Select(key=>key.CategoryID).FirstOrDefault() })
ShowCategories.cshtml
#model IEnumerable<TestDataBase.Models.Category>
#{
ViewBag.Title = "ShowCategories";
}
<h2>ShowCategories</h2>
<table>
#foreach(var item in Model )
{
<tr>
<td>
#item.CategoryName
</td>
<td>
#Html.ActionLink("ShowBooksFromCategory", "ShowBooksFromCategory", new { id=item.CategoryID})
</td>
</tr>
}
</table>
Models:
public partial class Books
{
public int CategoryID { get; set; }
public string BookName { get; set; }
public int BookID { get; set; }
}
public partial class Category
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
}
Hi #A191919 To redirect with an int you can do the following (this is exactly the same thing you did within your actionlink to get the first form..)
return RedirectToAction("ShowBooksFromCategory", new { id = book.CategoryID });
To get the ID into your form you could use ViewBag.
public ActionResult AddBookInCategory(int id)
{
ViewBag.id = id;
return View();
}
The use the viewbag value to fill in your form input.
i am trying to create user reviews under each product, i used Html.RenderAction
Html.RenderAction("ProductReviewTest", new { id = productids });
it works fine but it takes 9.4s to load the product page with the reviews, so tried Html.RenderPartial but gives error
my product view:
#model MVCProduct.Models.Product
<!--here displaying products-->
<!--displaying reviews in same view-->
<div class="display-field">
<p> Reviews for #Html.DisplayFor(model => model.ProductTitle) </p>
#{
int productid = Model.ProductID;
Html.RenderPartial("ProductReviewTest", new { id = productid });
}
</div>
my review view model:
public class ProductViewModel
{
public int ReviewId { get; set; }
public int? ProductID { get; set; }
public string ReviewTitle { get; set; }
public string ReviewMessage { get; set; }
public int? Rating { get; set; }
public string CustomerName { get; set; }
public string ReviewStatus { get; set; }
}
my ViewResult:
public PartialViewResult ProductReviewTest(int id)
{
List<ProductViewModel> productviewmodel = (from a in dbo.ProductReviews
where a.ProductID ==id
select new ProductViewModel
{
ReviewId=a.ReviewId,
ProductID=a.ProductID,
ReviewTitle =a.ReviewTitle,
ReviewMessage =a.ReviewMessage,
Rating =a.Rating,
CustomerName =a.CustomerName,
ReviewStatus=a.ReviewStatus
}).ToList();
return PartialView(productviewmodel);
}
my review view:
#model IEnumerable<MVCProduct.Models.ProductViewModel>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.ReviewId)
</th>
.......
</table>
error:
The model item passed into the dictionary is of type
'<>f__AnonymousType51[System.Int32]', but this dictionary requires a
model item of type
'System.Collections.Generic.IEnumerable1[Review.Models.ProductViewModel]'.
any help would be great.
There is a difference between RenderAction and RenderPartial. In the first you are calling action, but in second, you are directly calling partial view.
So you cannot pass productId in RenderPartial, instead you need to pass List<ProductViewModel>. Also in RenderPartial, you need to give partial view name, not the action name.
ViewResult:
public PartialViewResult ProductReviewTest()
{
return PartialView();
}
product view:
#model MVCProduct.Models.Product
<!--here displaying products-->
<!--displaying reviews in same view-->
<div class="display-field">
<p> Reviews for #Html.DisplayFor(model => model.ProductTitle) </p>
#{
int productid = Model.ProductID;
Html.RenderPartial("ProductReviewTest", Model.ProductReviews });
}
</div>
you are returning a List of ProductViewModel to view.
Instead use
var productviewmodel = (from a in dbo.ProductReviews
where a.ProductID ==id
select new ProductViewModel
{
ReviewId=a.ReviewId,
ProductID=a.ProductID,
ReviewTitle =a.ReviewTitle,
ReviewMessage =a.ReviewMessage,
Rating =a.Rating,
CustomerName =a.CustomerName,
ReviewStatus=a.ReviewStatus
}).FirstOrDefault();
return PartialView(productviewmodel);
I use #Html.DropDownList in a partial view for show the list of banks and render it in the Bank Branch view.
How can i get the selected Bank in #Html.DropDownList and fill the BankId in the BankBranchModel .
here is my code:
BankBranchModel :
public class BankBranchModel : BaseModel
{
public int? **BankID** { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
}
My partial view :
#Html.DropDownList("Banks", Model , "- Please Select -"})
BankBranch View:
#model MvcFirstSample.Models.BankBranchModel
#{
ViewBag.Title = "create";
}
<h2>create</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<div class="editor-field">
**#Html.Action("GetAllBank", "BankBranch")**
</div>
GetAllBanks for return the Partial view:
public ActionResult GetAllBank()
{
var Banks = Context.Banks.ToList();
List<BankLookup> BankLookupList = new List<BankLookup>();
var listItems = new List<SelectListItem>();
foreach (var Bank in Banks)
{
listItems.Add(new SelectListItem { Text = Bank.Name, Value = Bank.Id.ToString()});
}
**return PartialView("BankLookup", listItems);**
}
Why you don't want to use ViewBag?
In your Partial View you can say:
#Html.DropDownList("listItems",(IEnumerable<SelectListItem>)ViewBag.listItems )
, then use Jquery to get selected item:
var selectBanks= $("#listItems");
var selectedOptionId = selectBanks.find("option:selected").val();
Then populate input for bankid assuming it has id of bankid:
$("#bankid").val(selectedOptionId);
Here is one way...
In your Partial View:
#Html.DropDownList("bank_list")
In your controller, populate the list by binding ids and values:
ViewBag.bank_list = new SelectList(listItems, "Text", "Value");
I've been reading the various posts on view models and check boxes, but my brain is starting to lock up and I need a little push in the right direction.
Here's my simplified view model. I have checkboxes that need to populate the lists with their values. I don't think this can happen automagically. I'm not sure how to bridge the gap between an array of string values and a List correctly. Suggestions?
public int AlertId { get; set; }
public List<int> UserChannelIds { get; set; }
public List<int> SharedChannelIds { get; set; }
public List<int> SelectedDays { get; set; }
Have your View Model like this to represent the CheckBox item
public class ChannelViewModel
{
public string Name { set;get;}
public int Id { set;get;}
public bool IsSelected { set;get;}
}
Now your main ViewModel will be like this
public class AlertViewModel
{
public int AlertId { get; set; }
public List<ChannelViewModel> UserChannelIds { get; set; }
//Other Properties also her
public AlertViewModel()
{
UserChannelIds=new List<ChannelViewModel>();
}
}
Now in your GET Action, you will fill the values of the ViewModel and sent it to the view.
public ActionResult AddAlert()
{
var vm = new ChannelViewModel();
//The below code is hardcoded for demo. you mat replace with DB data.
vm.UserChannelIds.Add(new ChannelViewModel{ Name = "Test1" , Id=1});
vm.UserChannelIds.Add(new ChannelViewModel{ Name = "Test2", Id=2 });
return View(vm);
}
Now Let's create an EditorTemplate. Go to Views/YourControllerName and Crete a Folder called "EditorTemplates" and Create a new View there with the same name as of the Property Name(ChannelViewModel.cshtml)
Add this code ro your new editor template.
#model ChannelViewModel
<p>
<b>#Model.Name</b> :
#Html.CheckBoxFor(x => x.IsSelected) <br />
#Html.HiddenFor(x=>x.Id)
</p>
Now in your Main View, Call your Editor template using the EditorFor Html Helper method.
#model AlertViewModel
<h2>AddTag</h2>
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(m => m.AlertId)
#Html.TextBoxFor(m => m.AlertId)
</div>
<div>
#Html.EditorFor(m=>m.UserChannelIds)
</div>
<input type="submit" value="Submit" />
}
Now when You Post the Form, Your Model will have the UserChannelIds Collection where the Selected Checkboxes will be having a True value for the IsSelected Property.
[HttpPost]
public ActionResult AddAlert(AlertViewModel model)
{
if(ModelState.IsValid)
{
//Check for model.UserChannelIds collection and Each items
// IsSelected property value.
//Save and Redirect(PRG pattern)
}
return View(model);
}
Part of My View Model:
public List<int> UserChannelIds { get; set; }
public List<int> SharedChannelIds { get; set; }
public List<int> Weekdays { get; set; }
public MyViewModel()
{
UserChannelIds = new List<int>();
SharedChannelIds = new List<int>();
Weekdays = new List<int>();
}
I used partial views to display my reusable checkboxes (I didn't know about editor templates at this point):
#using AlertsProcessor
#using WngAlertingPortal.Code
#model List<int>
#{
var sChannels = new List<uv_SharedChannels>();
Utility.LoadSharedChannels(sChannels);
}
<p><strong>Shared Channels:</strong></p>
<ul class="channel-list">
#{
foreach (var c in sChannels)
{
string chk = (Model.Contains(c.SharedChannelId)) ? "checked=\"checked\"" : "";
<li><input type="checkbox" name="SharedChannelIds" value="#c.SharedChannelId" #chk /> #c.Description (#c.Channel)</li>
}
}
All three checkbox partial views are similar to each other. The values of the checkboxes are integers, so by lining up my view model List names with the checkbox names, the binding works.
Because I am working in int values, I don't feel like I need the extra class to represent the checkboxes. Only checked checkboxes get sent, so I don't need to verify they are checked; I just want the sent values. By initializing the List in the constructor, I should be avoiding null exceptions.
Is this better, worse or just as good as the other solution? Is the other solution (involving an extra class) best practice?
The following articles were helpful to me:
http://forums.asp.net/t/1779915.aspx/1?Checkbox+in+MVC3
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Binding list with view model
This site handles it very nicely
https://www.exceptionnotfound.net/simple-checkboxlist-in-asp-net-mvc/
public class AddMovieVM
{
[DisplayName("Title: ")]
public string Title { get; set; }
public List<CheckBoxListItem> Genres { get; set; }
public AddMovieVM()
{
Genres = new List<CheckBoxListItem>();
}
}
public class MembershipViewData
{
public MembershipViewData()
{
GroupedRoles = new List<GroupedRoles>();
RolesToPurchase = new List<uint>();
}
public IList<GroupedRoles> GroupedRoles { get; set; }
public IList<uint> RolesToPurchase { get; set; }
}
//view
#model VCNRS.Web.MVC.Models.MembershipViewData
#{
ViewBag.Title = "MembershipViewData";
Layout = "~/Views/Shared/_Layout.cshtml";
int i = 0;
}
#using (Html.BeginForm("Membership", "Account", FormMethod.Post, new { id = "membershipForm" }))
{
<div class="dyndata" style="clear: left;">
<table width="100%" cellpadding="0" cellspacing="0" class="table-view list-view">
foreach (var kvp2 in Model.GroupedRoles)
{
string checkBoxId = "RolesToPurchase" + kvp2.RoleType;
<tr>
<td width="240px">
<label class="checkbox-label" for="#checkBoxId">
<input type="checkbox" class="checkbox" name="RolesToPurchase[#i]"
id="#checkBoxId" value="#kvp2.RoleType" />
#kvp2.Key
</label>
</td>
</tr>
i++;
}
<tr style="background-color: #ededed; height: 15px;">
<td colspan="5" style="text-align: right; vertical-align: bottom;">
#Html.SubmitButton(Resources.MyStrings.Views_Account_Next)
</td>
</tr>
</table>
</div>
}
//Post Action
[HttpPost]
public ActionResult Membership(MembershipViewData viewData)
{
..........................
}
}
I am new to MVC and am trying to populate a DropDownList in my view with a list of 'rules' from my controller. When I do it the way listed, I just get a dropdownlist with a bunch of items that say CellularAutomata.Models.Rules. I know I am doing this incorrectly, I'm just wondering how I actually get it to show the rule description for each rule in the dropdownlist.
I have a Model
public class Rule
{
public int ID { get; set; }
public int Name { get; set; }
public string Description{ get; set; }
public Rule(int name, string description)
{
Name = name;
Description = description;
}
public Rule()
{
Name = 0;
Description = "";
}
}
A Controller
public ActionResult Index()
{
var rules = from rule in db.Rules
select rule;
return View(rules.ToList());
}
And a view
#model IEnumerable<CellularAutomata.Models.Rule>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<table>
<tr>
<td>
#Html.DropDownList("Test", new SelectList(Model))
</td>
</tr>
</table>
You could have a view model:
public class MyViewModel
{
public string SelectedRuleId { get; set; }
public IEnumerable<Rule> Rules { get; set; }
}
and then in your controller:
public ActionResult Index()
{
var model = new MyViewModel
{
Rules = db.Rules
};
return View(model);
}
and in the view:
#model CellularAutomata.Models.MyViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Html.DropDownListFor(
x => x.SelectedRuleId,
new SelectList(Model.Rules, "ID", "Description")
)