I have 2 methods like this
public ViewResult Detail(int Id)
{
if (Id != null)
{
Context context = new Context();
Poll PollDetail = context.Polls.FirstOrDefault(x => x.Id == Id);
PollDetail.Answers = new List<Answer>();
Context Context = new Context();
PollDetail.Answers = Context.Answers.Where(x => x.PollId == PollDetail.Id).ToList();
return View("../Home/Index", PollDetail);
}
RedirectToAction("Index", "Home");
}
[HttpPost]
public ActionResult PollVote(Poll CurrentPoll)
{
Context Context = new Context();
foreach (Answer item in CurrentPoll.Answers)
{
item.VoteCount = item.VoteCount + 1;
}
return View();
}
There cshtml. so there is no problem to this section.
<div class="container">
#Html.Partial("Header")
#if (Model == null)
{
#Html.Partial("CreatePoll")
}
else
{
using (#Html.BeginForm("PollVote", "Poll", FormMethod.Post, new { id = "PollVoteForm" }))
{
<div class="row-fluid">
<div class="span12 pageHeader">
<h2>SORU:</h2>
#Html.LabelFor(m => m.Question, Model.Question, new { #class = "question-input", #id = "question" })
</div>
</div>
<div id="answers" class="row-fluid">
#foreach (Answer answer in Model.Answers)
{
<p class="external">
#Html.RadioButtonFor(m => answer.Content, answer.Content, new { #name = "rb", #class = "answer-radio", #id = "answer-" + answer.Counter, #checked = "false" })
#Html.Label(answer.Content, new { #for = "answer-" + answer.Counter })
#Html.HiddenFor(m => answer.Content)
</p>
}
</div>
<div class="row-fluid">
<div class="span6"></div>
<div class="span5">
<input type="submit" value="Oyla" class="btnPS" />
</div>
</div>
}
}
<div class="footer"></div>
</div>
Poll model perfectly binded. But i cant back any data. when i submit form in index.cshtml. CurrentPoll model comes null. How can i fix it ?
Asp.Net MVC require propertioes on your model in order for the model binding. Hence check your model and ensure all members are exposed as properties.
Eg: You change your model to something like below.
public class Poll
{
public Answer Answers { get; set; }
}
Related
This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Pass List of Checkboxes into View and Pull out IEnumerable [duplicate]
(2 answers)
Closed 4 years ago.
I am new to MVC. I have a Edit view which has some fields related to Page Menu like Name, Url etc. In the same view i have List of page roles(Admin, Customer etc) displayed as Checkboxes. In the Edit Get Request, some checkboxes are displayed selected based on the database values for that particular Page Menu.
Eg, if Admin and customer are authorized to view that particular page, only Admin and Customer roles checkboxes are displayed selected in the Edit Get Request.
I Have three tables Page, roles and PageRole table connecting the other two tables.
Now if the user edits the Page and Checks/Unchecks checkboxes, i need help on how to save the data back to tables based on the checkbox selection in Edit Post action.
My Edit View Model Class:
public class PageAdminEditViewModel : PageAdminViewModel
{
public virtual SelectList PageList { get; set; }
public IList<PageRoleData> PageRoleData { get; set; }
}
My Model class for Checkboxes:
public class PageRoleData
{
public string ASPNetRoleID { get; set; }
public string PageRoleID { get; set; }
public int PageID { get; set; }
public string RoleName { get; set; }
public bool Selected { get; set; }
}
MY EDIT Get Action Method:
public ActionResult Edit(int id)
{
if (ModelState.IsValid)
{
try
{
var pData = m_pas.Get<PageAdminEditViewModel>(id);
var data = m_pas.GetAll(true);
SelectList pageList
= new SelectList(data,
nameof(PageAdminEditViewModel.Pageid),
nameof(PageAdminEditViewModel.Pagename));
IList<PageRoleData> pageRoleData = m_pas.GetPageRolesByPageID(id);
pData.PageList = pageList; // For Dropdownlist values
pData.PageRoleData = pageRoleData; // For Checkboxes values
return View(pData);
}
catch (Exception ex)
{
s_log.Fatal($"An error occurred when calling the Edit Page. {ex.Message}", ex);
}
}
return View();
}
My EDIT POST Action:
[HttpPost]
public ActionResult Edit(int id, PageAdminEditViewModel editViewModel)
{
try
{
m_uow.BeginTransaction();
m_pas.CreateOrEdit(id, editViewModel);
m_uow.Commit();
return RedirectToAction("Index");
}
catch (Exception ex)
{
s_log.Fatal($"An error occurred while saving the changes on the Edit Page. {ex.Message}", ex);
}
return View();
}
My Service Layer CreateorEdit() method for Post Request
public void CreateOrEdit(int id, PageAdminEditViewModel viewModel)
{
Page pageData = null;
// Checks whether to create a new Page
if (id <= 0)
{
pageData = new Page();
}
else
{
pageData = m_uow.QueryFactory.ObjectQuery.Get<Page, int>(id);
}
// Checks if the Page has a Parent Page associated with it
if (pageData.ParentNodeID != null)
{
// Checks if the user has changed the existing Parent page and assigns the new Parent Page accordingly
if (viewModel.ParentNodeID != pageData.ParentNodeID.Pageid)
{
var newParentPage = m_uow.QueryFactory.ObjectQuery.Get<Page, int>(viewModel.ParentNodeID);
pageData.ParentNodeID = newParentPage;
}
}
// In case there is no Parent Page, Checks if the user has set any Parent Page and assigns accordingly
else if (viewModel.ParentNodeID != 0)
{
var newParentPage = m_uow.QueryFactory.ObjectQuery.Get<Page, int>(viewModel.ParentNodeID);
pageData.ParentNodeID = newParentPage;
}
pageData.Pagename = viewModel.Pagename;
if (viewModel.ParentNodeID != 0)
pageData.ParentNodeID.Pageid = viewModel.ParentNodeID;
else
pageData.ParentNodeID = null;
pageData.Url = viewModel.Url;
pageData.Iconimage = viewModel.Iconimage;
pageData.Pagevisibility = viewModel.Pagevisibility;
pageData.Displayorder = viewModel.Displayorder;
var pData = Mapper.Map<Page, PageDto>(pageData);
IList<PageRoleData> selectedRoles = viewModel.PageRoleData;
m_uow.AddOrUpdate(pageData);
}
My EDIT View:
#model ISPC.CustomerWebsite.Areas.PageAdministration.ViewModels.PageAdminEditViewModel
#{
if (Model.Pageid <= 0)
{
ViewBag.Title = "Create Page Menu";
}
else
{
ViewBag.Title = "Edit Page Menu";
}
}
#if (Model.Pageid <= 0)
{
<h2>Create Page Menu</h2>
}
else
{
<h2>Edit Page Menu</h2>
}
<br />
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="container-fluid" style="float: left; width: 60%;">
<div class="editor-label">
#Html.LabelFor(model => model.Pagename)
<div class="editor-field">
#Html.TextBoxFor(model => model.Pagename, new { style = "width: 200px" })
#Html.ValidationMessageFor(model => model.Pagename)
</div>
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.ParentNodeID)
<div class="editor-field">
#Html.DropDownListFor(model => model.ParentNodeID, Model.PageList, "-Select-", new { style = "width: 200px" })
#Html.ValidationMessageFor(model => model.Pagename)
</div>
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.Url)
<div class="editor-field">
#Html.TextBoxFor(model => model.Url, new { style = "width: 200px" })
#Html.ValidationMessageFor(model => model.Url)
</div>
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.Iconimage)
<div class="editor-field">
#Html.TextBoxFor(model => model.Iconimage, new { style = "width: 200px" })
#Html.ValidationMessageFor(model => model.Iconimage)
</div>
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.Pagevisibility)
<div class="editor-field">
#Html.EditorFor(model => model.Pagevisibility)
#Html.ValidationMessageFor(model => model.Pagevisibility)
</div>
</div><br />
<div class="editor-label">
#Html.LabelFor(model => model.Displayorder)
<div class="editor-field">
#Html.TextBoxFor(model => model.Displayorder, new { style = "width: 200px" })
#Html.ValidationMessageFor(model => model.Displayorder)
</div>
</div><br />
<div>
#Html.HiddenFor(model => model.Pageid)
</div><br />
<div class="row">
<div>
<input type="submit" value="Save" class="btn btn-default" /> |
#Html.ActionLink("Back to List", "Index")
</div>
</div>
</div><br />
<div class="form-group">
<label class="col-md-pull-2 control-label">
Select User Role :
</label><br />
<div class="col-md-pull-2">
#foreach(var item in Model.PageRoleData)
{
if (item.PageRoleID != null)
{
item.Selected = true;
}
else
{
item.Selected = false;
}
#Html.HiddenFor(model => item.ASPNetRoleID)
#Html.CheckBoxFor(model => item.Selected, new { #id = "chkbox1", #class = "form-check" })
<text> </text>
#Html.LabelFor(model => item.RoleName, item.RoleName)<br />
}
</div>
</div>
}
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.
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);
}
}
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.