I am making my MVC application. I created a view, in which a user picks data from dropdown list. The view is like this:
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#using ClassDeclarationsThsesis.Classes
#using Microsoft.Ajax.Utilities
#model ClassDeclarationsThsesis.Models.ClassesViewModel
#{ ViewBag.Title = "Classes";
}
<h2>Classes</h2>
#foreach (var user in Model.users)
{
if (user.email.Replace(" ", String.Empty) == HttpContext.Current.User.Identity.Name)
{
if (user.user_type.Replace(" ", String.Empty) == 3.ToString() || user.user_type.Replace(" ", String.Empty) == 2.ToString())
{
using (Html.BeginForm("Classes", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Generate summary views</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#{
List<SelectListItem> listItems1 = new List<SelectListItem>();
}
#foreach (var subject in Model.subject)
{
listItems1.Add(new SelectListItem
{
Text = subject.name,
Value = subject.name,
});
}
#Html.LabelFor(m => m.subject_name, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.subject_name, listItems1, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Submit" />
</div>
</div>
}
}
if (user.user_type.Replace(" ", String.Empty) == 1.ToString())
{
<p>You do not have enough permissions to enter this page. Contact the administrator.</p>
}
}
}
The controller is:
public ActionResult Classes()
{
ClassDeclarationsDBEntities1 entities = new ClassDeclarationsDBEntities1();
var model = new ClassesViewModel();
model.subject = entities.Subjects.ToList();
model.users = entities.Users.ToList();
if (ModelState.IsValid)
{
return RedirectToAction("ClassesPickGroup", "Account", new { subject_name=model.subject_name});
}
return View(model);
}
And the model:
public class ClassesViewModel
{
public List<Subject> subject { set; get; }
public List<User> users { get; set; }
[Required]
[Display(Name = "Subject")]
public string subject_name { get; set; }
}
But since the view only contains a single dropdown list, it is always Valid and redirects to different view straight away. How do I make the application wait for user choice in dropdown list and then submit the answer?
There is no problem in your view, but the problem that you create new object every time user submit and check for validation
public ActionResult Classes(ClassesViewModel model)
{
ClassDeclarationsDBEntities1 entities = new ClassDeclarationsDBEntities1();
if (ModelState.IsValid)
{
return RedirectToAction("ClassesPickGroup", "Account", new { subject_name=model.subject_name});
}
else {
model.subject = entities.Subjects.ToList();
model.users = entities.Users.ToList();
return View(model);
}
}
Related
I am trying to list a list of products by category value. The value of the category is the description of the product, if the product is an apple, the category will be Fruit. So I want the user to be able to choose the category, click a button, and list all the products with the same category. I'm trying do this, select category and list by category on a same View.
The model:
public partial class product
{
int id {get; set}
string name {get; set}
string category {get; set;}
}
The Controller:
[HttpGet]
public ActionResult ListByCat()
{
List<SelectListItem> lst = new List<SelectListItem>();
lst.Add(new SelectListItem() { Text = "Fruits", Value = "fruits" });
lst.Add(new SelectListItem() { Text = "Hardware", Value = "hardware"});
lst.Add(new SelectListItem() { Text = "Vegetables", Value = "vegetables"});
ViewBag.category = lst;
return View();
}
[HttpPost]
public ActionResult listByCat(product prod)
{
using (inventarioEntitiesDBA dc = new inventarioEntitiesDBA())
{
return View(dc.product.Where(a => a.category == prod.category).ToList());
}
}
And the view:
#model regMVC.Models.product
#{
ViewBag.Title = "listByCat";
}
<h2>listByCat</h2>
#using (Html.BeginForm())
{
<div class="form-group">
#Html.LabelFor(model => model.category, htmlAttributes: new { #class = "control- label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("category", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.category, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="List by Category" class="btn btn-default" />
</div>
</div>
ViewModel
public class ListByCatViewModel
{
//This hold the selected value in post action
public string SelectedCategory { get; set; }
public List<SelectListItem> Categories { get; set; } = new List<SelectListItem>();
public List<Product> SearchResults { get; set; } = new List<Product>();
}
listByCat() GET Action, here we pass the ViewModel to the view
public ActionResult listByCat()
{
ListByCatViewModel listByCatViewModel = new ListByCatViewModel();
listByCatViewModel.Categories = buildCategories();
return View(listByCatViewModel);
}
Now the POST action, finding the result from the database, I am mocking the result from a list
[HttpPost]
public ActionResult listByCat(ListByCatViewModel listByCatViewModel)
{
if (ModelState.IsValid)
{
if (listByCatViewModel.SelectedCategory != null)
{
//Binding dropdown again
listByCatViewModel.Categories = buildCategories(listByCatViewModel.SelectedCategory);
var products = mockProductCollection();
var results = products.FindAll(x => x.category.ToLower() ==
listByCatViewModel.SelectedCategory.ToLower());
listByCatViewModel.SearchResults = results;
}
}
return View(listByCatViewModel);
}
My Helper method to fill Dropdownlist and Product list
private List<SelectListItem> buildCategories(string selectedItem = "")
{
List<SelectListItem> lst = new List<SelectListItem>();
lst.Add(new SelectListItem() { Text = "Fruits", Value = "fruits" });
lst.Add(new SelectListItem() { Text = "Hardware", Value = "hardware" });
lst.Add(new SelectListItem() { Text = "Vegetables", Value = "vegetables" });
if (!string.IsNullOrEmpty(selectedItem))
{
lst.Find(x => x.Value.ToLower() == selectedItem.ToLower()).Selected = true;
}
return lst;
}
private List<Product> mockProductCollection()
{
List<Product> products = new List<Product>() {
new Product(){id=1,category="fruits",name="Apple"},
new Product(){id=2,category="fruits",name="Banana"},
new Product(){id=3,category="hardware",name="Screws"},
new Product(){id=4,category="hardware",name="Bolt"},
new Product(){id=5,category="vegetables",name="Carrot"},
new Product(){id=6,category="vegetables",name="Cucumber"}
};
return products;
}
and finally the View
#model NETMVC.ViewModel.ListByCatViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
<div class="form-group">
#Html.LabelFor(model => model.Categories, htmlAttributes: new { #class = "control- label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.SelectedCategory,Model.Categories, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Categories, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="List by Category" class="btn btn-default" />
</div>
</div>
}
#if (Model.SearchResults != null && Model.SearchResults.Count > 0)
{
<ul>
<li>Search Results</li>
#foreach (var product in Model.SearchResults)
{
<li>#product.name</li>
}
</ul>
}
I have a list-box with options. User can select all or select any one, so all i need is to bind the selected to the model on the controller.Now it comes as empty even though i have selected some.
I have populated the data to the List-box already. LoadAllControls method is in the index controller.
Loading data to List-box. This works 100%
public void LoadAllControls(myModel model)
{
try
{
string jsonReq = null;
string jsonResp = null;
//API call here
jsonResp = JsonWrapper.JsonGET(jsonReq);
List<Structs> listOrderTypes = DeserialiseFromJson<List<Structs>>.Deserialise(jsonResp);
List<SelectListItem> listO = listOrderTypes.Select(item => new SelectListItem
{
Value = item.orderType.ToString(),
Text = item.orderTypeName,
Selected = "-1" == (item.orderTypeCode.ToString()) ? true : false
}).ToList();
model.orderTypes = new List<SelectListItem>(listO);
}
catch(Exception exx)
{
throw exx;
}
}
View
#using (Ajax.BeginForm("Search", "myController", new AjaxOptions { HttpMethod = "Post" }))
{
<div class="form-group">
<label class="control-label col-sm-2" for="txtfrom">Order Type:</label>
<div class="col-md-4">
#Html.ListBoxFor(m => m.orderTypesIds, Model.orderTypes, new { #class = "form-control listbox", id = "orderTypeIdList", #multiple = "multiselect" })
</div>
</div>
<div class="form-group">
<div class="col-sm-10 col-sm-offset-2">
<button class="btn btn-primary " id="btnSearch" name="SearchButton" type="submit">
Search
</button>
</div>
</div>
}
Controller
public ActionResult Search(myModel model)
{
//Selected options comes as null to the model
//Some logic here
}
My Model
public class myModel
{
public List<SelectListItem> orderTypes { get; set; }
public int[] orderTypesIds { get; set; }
}
Here is my view:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NHibernate.AspNet.Identity;
namespace MyProject.Web.Models
{
public class IdentityRoleView
{
public virtual string Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<IdentityUser> Users { get; set; }
}
}
Here is my controller:
[HttpGet]
public ActionResult Edit(string roleId)
{
IdentityRole role = Service.Find(roleId);
return View("Edit", AutoMapper.Mapper.Map<IdentityRoleView>(role));
}
[HttpPost]
public ActionResult Edit(IdentityRoleView role)
{
Service.Update(role);
TempData["Comment"] = "The record was updated";
return RedirectToAction("Index");
}
}
Here is my view:
#model MyProject.Web.Models.IdentityRoleView
#{
ViewBag.Title = "Edit";
Layout = "~/Areas/Administration/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Id);
<div>
Role name
</div>
<p>
#Html.TextBoxFor(model => model.Name)
</p>
for (int items = 0; items < Model.Users.Count; items++)
{
#Html.DisplayFor(m => m.Users[items].Id);
#Html.DisplayFor(m => m.Users[items].UserName);
}
<input type="submit" value="Save" />
}
IdentityRoleView.Users is always null when it is passed back to the controller. What is the problem? I can see IdentityRoleView.Users on the view - they are all deleted when posted back to the server as IdentityRoleView.Users is always null.
This is a bit of a quirk of MVC.
What you have is mostly correct.
Your controller is just fine:
[HttpGet]
public ActionResult Index()
{
Person p1 = new Person();
p1.name = "Ian";
List<Sport> sports = new List<Sport>();
Sport s1 = new Sport();
s1.description = "Football";
sports.Add(s1);
Sport s2 = new Sport();
//s1.description = "Netball"; I'm guessing this is a typo?
s2.description = "Netball";
sports.Add(s2);
p1.sports = sports;
return View("Person", p1);
}
[HttpPost]
public ActionResult Index(Person p1)
{
return View();
}
However, its the view that has the issue:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Person</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.name, "", new { #class = "text-danger" })
</div>
</div>
#* This is the key difference here *#
#for (int items = 0; items < Model.sports.Count; items++)
{
<div>
#Html.DisplayFor(sport => Model.sports[items].description)
#Html.HiddenFor(sport => Model.sports[items].description)
<hr />
</div>
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default"/>
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
So let me explain.
What I did was moved your sports list into the Form(){}. This needs to be done in order to actually have the form pass the objects back. Whatever is in that Form is what it is going to post back.
Another thing you have to do is give the form something to actually bind the model object to.
The #Html.DisplayFor helper won't do it, and since it appears you don't want users changing the sports, you can simply create a #Html.HiddenFor. This will pass back the values to your [HttpPost] Index(Person p1) method.
What you do after that, is up to you.
Hope this helps.
Here is the viewmodel
public class IdentityRoleView
{
public IdentityRoleView()
{
Users = new List<IdentityUser>();
}
public virtual string Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<IdentityUser> Users { get; set; }
}
The Controller Methods
public ActionResult Edit(string roleId)
{
IdentityRoleView model = new IdentityRoleView();
model.Name = "IdentityRoleViewUser";
model.Id = "2";
model.Users.Add(new IdentityUser {
UserName = "testuser",
Id = "1",
Email = "test#test.com"
});
model.Users.Add(new IdentityUser
{
UserName = "testuser2",
Id = "2",
Email = "test#test2.com"
});
return View("Edit", model);
}
[HttpPost]
public ActionResult Edit(IdentityRoleView model)
{
//Your logic
return RedirectToAction("Index");
}
Then View
#model MyProject.Web.Models.IdentityRoleView
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Id);
<div>
Role name
</div>
<p>
#Html.TextBoxFor(model => model.Name)
</p>
for (int i = 0; i < Model.Users.Count(); i++)
{
#Html.TextBoxFor(model => model.Users[i].Email)
#Html.TextBoxFor(model => model.Users[i].UserName)
}
<input type="submit" value="Save" />
}
If you want that user can not edit value then make TextBoxFor readonly.
I have a MVC Application with Index and Detail view. Index show _peticiones list items. And I want to update this list from Detail view.
Detail View
#using (Html.BeginForm())
{
<div class="form-group">
<label for="id">Id:</label>
#Html.TextBoxFor(m => m.Id, new { #id = "id", #class = "form-control", #readonly = "readonly" })
</div>
<div class="form-group">
<label for="nombre">Nombre:</label>
#Html.TextBoxFor(m => m.Nombre, new { #nombre = "nombre", #class = "form-control"})
</div>
<div class="form-group">
<label for="desc">Descripcion:</label>
#Html.TextBoxFor(m => m.Desc, new { #dec = "desc", #class = "form-control"})
</div>
<div class="form-group">
<label for="fecha">Fecha:</label>
#Html.TextBoxFor(m => m.Fecha, new { #fecha = "fecha", #class = "form-control"})
</div>
<div class="form-group">
<label for="activo">Activo:</label>
#Html.TextBoxFor(m => m.Activo, new { #activo= "activo", #class = "form-control" })
</div>
<div class="container-fluid">
<div class="col-md-12 text-right">
<input type="submit" value="Guardar" class="btn btn-primary" />
</div>
</div>
}
Controller (Update method has "id" as parameter, i can't use object like a parameter)
public ActionResult Detail(Peticion peticion)
{
if (ModelState.IsValid)
{
var id = peticion.Id;
_peticionService.Update(id);
return RedirectToAction("Index");
}
return View();
}
Class PeticionService
public bool Update(int id)
{
if (id > 0)
{
var peticionOld = _peticiones.FirstOrDefault(u => u.Id == id);
if (peticionOld != null)
{
//How to update item list??
return true;
}
}
return false;
}
How can I update list from "PeticionService" class with just id?
I would approach your problem like the below.
Create a view model for your view.
public class PeticoneViewModel
{
public Peticione CurrentPeticione { get; set; }
}
Then have a service that handles the retrieval and updates to the list source.
public class PeticoneService
{
public Peticione GetPeticioneByID(int id)
{
//Put your implementation here.
return new Peticione();
}
public bool SavePeticioneByID(int id, string newValue)
{
//Put your implementation here.
return true;
}
}
Then create a controller to return the Detail view and handle the update
public class PeticioneController : Controller
{
public ActionResult Detail(int peticonID)
{
var peticoneService = new PeticoneService();
var peticoneViewModel = new PeticoneViewModel();
peticoneViewModel.CurrentPeticione = peticoneService.GetPeticioneByID(peticonID);
return View("Detail",peticoneViewModel);
}
public bool UpdatePeticone(int id, string newValue)
{
if (id > 0)
{
var peticoneService = new PeticoneService();
return peticoneService.SavePeticioneByID(id, newValue);
}
return false;
}
}
Also in an ideal world your service should be injected into the controller so the controller isn't responsible for the service instantiation. But that's another issue.
Hope the above helps.
How to create drop down list in Create.cshtml, where the list is made of data from DB and if there is no such kind of data you want to choose you can enter new value and it saves in DB.
I tried to query from DB to a list and used ViewBag.DropDownList (it worked in Index.cshtml, but not in Create.cshtml, because I was getting error: There is no ViewData item of type 'IEnumerable' that has the key "MyDropDownList")
Create.cshtml:
#using LicenseManager.Models
#model LicenseManager.Models.CompanyNames
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CompanyNames</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.DropDownList("CompanyNames", (SelectList)ViewBag.DropDownValues)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval") }
and controller CompanyNames.cs:
public class CompanyNamesController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: CompanyNames
public ActionResult Index()
{
ApplicationDbContext db = new ApplicationDbContext();
var querys = from c in db.CompanyNames
select c.Name;
ViewBag.DropDownValues = new SelectList(querys);
return View(db.CompanyNames.ToList());
}
}
Can someone help me with this? I just need some kind of direction where to go, to do. Sorry for the code....
model created :
public class CustomerModel
{
public List<SelectListItem> ListAdCode { get; set; }
}
Create a function to bind a list :
public static List<SelectListItem> AdCodeList()
{
List<SelectListItem> list = new List<SelectListItem>();
list.Add(new SelectListItem { Text = "--Select--", Value = null, Selected = true });
using (CrmKolmEntities entities = new CrmKolmEntities())
{
var allActiveCAdCodes = entities.AdCodes.Where(x => x.IsDeleted == false).ToList();
if (allActiveCAdCodes.Count() > 0)
{
foreach (var adCode in allActiveCAdCodes)
{
list.Add(new SelectListItem { Text = adCode.AdCodeName, Value = adCode.AdCodeId.ToString() });
}
}
}
return list;
}
On Controller :
public ActionResult ManipulateCustomer(int id, int? idOrder)
{
CustomerModel model = new CustomerModel();
model.ListAdCode = AdCodeList();
if (model.ListPriceList == null)
{
model.ListPriceList = CommonFunctions.PriceListActive(null);
}
return View(model);
}
On View:
#Html.DropDownListFor(r => r.AdCodeId, new SelectList(Model.ListAdCode, "value", "text", "selectedValue"), new { #class = "input", #style = "width:450px" })
I think you need Html.DropDownList instead of ViewBag.DropDownList. The former is from the HtmlHelper class and I think it's what you need. You can read more about it here.