MVC 3 Passing null from View to Controller - asp.net

Whenever I try to pass a value from the view to the controller using a model, it shows up in the controller as null. I tried something very similar in another part of the project and did not have this problem. Why is this coming back null?
Here is the code from the controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MovieProject2.Models;
namespace MovieProject2.Controllers
{
public class ReviewsController : Controller
{
public ActionResult Edit(int id = -1)
{
if (id < 0)
return HttpNotFound();
MovieReview review = MovieADO.getReviewByID(id);
return View(review);
}
[HttpPost]
public ActionResult Edit(MovieReview review)
{
if (review == null) return HttpNotFound();
return View(review);
}
}
View:
#model MovieProject2.Models.MovieReview
#{
ViewBag.Title = "Edit Review";
}
#{ //Not null here
if(#Model != null) {<h2>Edit Review for #Model.MovieReviewed.Title</h2>
<h4>Reviewed by #Model.Reviewer.Username</h4>}
else{<h2>Not Found</h2>
}
}
#using (Html.BeginForm())
{
Html.ValidationSummary(true);
<fieldset>
<div class="editor-label">
#Html.LabelFor(itemModel => Model.Rating)
</div>
<div class="editor-label">
#Html.EditorFor(itemModel => Model.Rating)
#Html.ValidationMessageFor(itemModel => Model.Rating)
</div>
<div class="editor-label">
#Html.LabelFor(itemModel => Model.Review)
</div>
<div class="editor-label">
#Html.EditorFor(itemModel => Model.Review)
#Html.ValidationMessageFor(itemModel => Model.Review)
</div>
<p>
<input type="submit" value="Change" />
</p>
</fieldset>
}
Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MovieProject2.Models
{
public class MovieReview
{
public int ReviewID { get; set; }
public Movie MovieReviewed { get; set; }
public User Reviewer { get; set; }
public int Rating { get; set; }
public string Review { get; set; }
public DateTime DateReviewed { get; set; }
public MovieReview() { }
}
}

Instead of
[HttpPost]
public ActionResult Edit(MovieReview review)
write
[HttpPost]
public ActionResult Edit(MovieReview model)
(and rename it further in that method from review to model. It should work.
OR
rename property of MovieReview.Review to something else (for example, Review1). You cannot have the same name for a property and passed model object (case insensitive)

You have to try this
#using (Html.BeginForm("Action methodName","controllerName"))

Related

why not display text Required in Html after submit radio button empty?

1.It delivers when you press the answer in the first question why ?
2.not display text Required in Html after submit radio button empty in span tag.
<span asp-validation-for="#item.CheckAns" class="text-danger"></span>
views/Homecontroller1/Index
This is CSHTML
#model List<QuestionCommentViewModel>
#{
ViewData["Title"] = "Index";
}
<div class="container">
<div class="row">
<div class="col-lg-12">
<form asp-action="Index" method="post">
#foreach (var item in Model)
{
<h3>#item.OneQuestions.TextQ</h3>
#foreach (var r in item.ListChoices)
{
<input type="radio" id="#r.Id" name="#r.Qid" asp-for="#item.CheckAns" value="#r.TextCh">
<label for="#r.Id">#r.TextCh</label><br>
<span asp-validation-for="#item.CheckAns" class="text-danger"></span>
}
}
<input type="submit" value="submit" style="background-color:dodgerblue;Color:white; border-radius:5px; font-weight:bold;" />
</form>
</div>
</div>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
model
using System.Threading.Tasks;
using Task222SchoolApp.Models;
namespace Task222SchoolApp.Models
{
public class QuestionCommentViewModel
{
public Question OneQuestions { get; set; }
public IQueryable<Choice> ListChoices { get; set; }
[BindProperty, Required(ErrorMessage = "Please choose Answer.")]
public virtual string CheckAns { get; set; }
}
}
controller
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using Task222SchoolApp.Models;
namespace WebApplication6.Controllers
{
public class HomeController1 : Controller
{
private readonly SchoolContext _context;
public HomeController1(SchoolContext context)
{
_context = context;
}
// GET: HomeController1
public IActionResult Index()
{
List<QuestionCommentViewModel> QCVM = new List<QuestionCommentViewModel>();
QCVM= GetQCVM();
// Console.WriteLine("qqqqqqq");
return View(QCVM);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(List<QuestionCommentViewModel> QCVM)
{
if (ModelState.IsValid)
{
}
return View();
}
private IQueryable<Question> getQustion()
{
var one = _context.Questions.Include(q => q.QidNavigation);
return one;
}
private List<QuestionCommentViewModel> GetQCVM()
{
Console.WriteLine("111222222222222222222");
var ListQuestion = getQustion();
List<QuestionCommentViewModel> QCVM=new List<QuestionCommentViewModel> ();
foreach (var item in ListQuestion)
{
var ch = _context.Choices.Include(q => q.QidNavigation).Where(q=>q.Qid==item.Id);
QCVM.Add(new QuestionCommentViewModel() { OneQuestions = item, ListChoices= ch });
// return QCVM;
}
return QCVM;
}
// GET: HomeController1/Details/5
public ActionResult Details(int id)
{
return View();
}
// GET: HomeController1/Create
public ActionResult Create()
{
return View();
}
// POST: HomeController1/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: HomeController1/Edit/5
public ActionResult Edit(int id)
{
return View();
}
// POST: HomeController1/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: HomeController1/Delete/5
public ActionResult Delete(int id)
{
return View();
}
// POST: HomeController1/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
}
}
You need to change your code like below
#foreach (var item in Model)
{
<h3>#item.OneQuestions.TextQ</h3>
#foreach (var r in item.ListChoices)
{
<input type="radio" id="#r.Id" asp-for="#item.CheckAns" value="#r.TextCh">
<label for="#r.Id">#r.TextCh</label><br>
}
<span asp-validation-for="#item.CheckAns" class="text-danger"></span>
}
Test Result:

The column name is not valid. [ Node name (if any) = Extent2,Column name = Course_CourseId ]

I always received this error as stated above.
I've recreated the Front Model and also the Front Controller yet I've received the same problem.
Front Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Module1.Models
{
public class Front
{
public int FrontId { get; set; }
public int ModuleId { get; set; }
public string Description { get; set; }
public string Code { get; set; }
public int TotalHrs { get; set; }
public int LectHrs { get; set; }
public int TutHrs { get; set; }
public int PracHrs { get; set; }
public int Year { get; set; }
public string Prerequisite { get; set; }
public virtual Module Module { get; set; }
}
}
Front Controller
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Module1.Models;
namespace Module1.Controllers
{
public class FrontController : Controller
{
private SchoolEntities db = new SchoolEntities();
//
// GET: /Topic/
public ViewResult Index()
{
var fronts = db.Fronts.Include(t => t.Module);
return View(fronts.ToList());
}
//
// GET: /Topic/Details/5
public ViewResult Details(int id)
{
var mod = db.Modules.Include("Fronts").Single(t => t.ModuleId == id);
return View(mod);
}
//
// GET: /Topic/Create
public ActionResult Create(int ID)
{
var modules = db.Modules.Where(m => m.ModuleId == ID).FirstOrDefault();
if (modules != null)
{
ViewBag.Code = modules.Code;
ViewBag.Description = modules.Description;
}
Front model = new Front();
model.ModuleId = ID;
return View(model);
}
//
// POST: /Topic/Create
[HttpPost]
public ActionResult Create(Front front)
{
if (ModelState.IsValid)
{
db.Fronts.Add(front);
db.SaveChanges();
return RedirectToAction("Details", new { id = front.ModuleId });
}
ViewBag.ModuleId = new SelectList(db.Modules, "ModuleId", "Code", front.ModuleId);
return View(front);
}
//
// GET: /Topic/Edit/5
public ActionResult Edit(int id)
{
var modules = db.Modules.Where(m => m.ModuleId == id).FirstOrDefault();
if (modules != null)
{
ViewBag.Code = modules.Code;
ViewBag.Description = modules.Description;
}
Front front = db.Fronts.Find(id);
ViewBag.ModuleId = new SelectList(db.Modules, "ModuleId", "Code", front.ModuleId);
return View(front);
}
//
// POST: /Topic/Edit/5
[HttpPost]
public ActionResult Edit(Front front)
{
if (ModelState.IsValid)
{
db.Entry(front).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Details", new { id = front.ModuleId });
}
ViewBag.ModuleId = new SelectList(db.Modules, "ModuleId", "Code", front.ModuleId);
return View(front);
}
//
// GET: /Topic/Delete/5
public ActionResult Delete(int id)
{
Front front = db.Fronts.Find(id);
return View(front);
}
//
// POST: /Topic/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Front front = db.Fronts.Find(id);
db.Fronts.Remove(front);
db.SaveChanges();
return RedirectToAction("Details", new { id = front.ModuleId });
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
The error above pops up when it is proceeding to my Front Details
Front Details View
#model Module1.Models.Front
#{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<fieldset>
<legend>Front</legend>
<div class="display-label">Module</div>
<div class="display-field">
#Html.DisplayFor(model => model.Module.Code)
</div>
<div class="display-label">ModuleName</div>
<div class="display-field">
#Html.DisplayFor(model => model.Description)
</div>
<div class="display-label">ModuleCode</div>
<div class="display-field">
#Html.DisplayFor(model => model.Code)
</div>
<div class="display-label">TotalHrs</div>
<div class="display-field">
#Html.DisplayFor(model => model.TotalHrs)
</div>
<div class="display-label">LectHrs</div>
<div class="display-field">
#Html.DisplayFor(model => model.LectHrs)
</div>
<div class="display-label">TutHrs</div>
<div class="display-field">
#Html.DisplayFor(model => model.TutHrs)
</div>
<div class="display-label">PracHrs</div>
<div class="display-field">
#Html.DisplayFor(model => model.PracHrs)
</div>
<div class="display-label">Year</div>
<div class="display-field">
#Html.DisplayFor(model => model.Year)
</div>
<div class="display-label">Prerequisite</div>
<div class="display-field">
#Html.DisplayFor(model => model.Prerequisite)
</div>
</fieldset>
<p>
#Html.ActionLink("Edit", "Edit", new { id=Model.FrontId }) |
#Html.ActionLink("Back to List", "Index")
</p>
<p>
#Html.ActionLink("Add Record", "Create", new { id = Model.ModuleId})
</p>
<p>
#Html.ActionLink("Back to Home", "Index", "SchoolManager")
</p>
MY ERROR
The column name is not valid. [ Node name (if any) = Extent2,Column name = Course_CourseId ]

Partial views inside my asp.net mvc will ignore all the model data annotations

I have the following action method which render the following partial view:-
public ActionResult CreateVMNetwork(int vmid)
{
AssignIps vmips = new AssignIps()
{
TechnologyIP = new TechnologyIP() { TechnologyID = vmid},
IsTMSIPUnique = true,
IsTMSMACUnique = true
};
return PartialView("_CreateNetworkInfo",vmips);
}
The partial view is :-
model TMS.ViewModels.AssignIps
#if (this.ViewContext.FormContext == null)
{
this.ViewContext.FormContext = new FormContext();
}
#using (Ajax.BeginForm("CreateVMNetwork", "VirtualMachine", new AjaxOptions
{
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = "networktable",
LoadingElementId = "loadingimag",
HttpMethod= "POST",
OnSuccess="submitform"
}))
{
#Html.ValidationSummary(true)
#Html.HiddenFor(model=>model.TechnologyIP.TechnologyID)
#Html.AntiForgeryToken()
<div>
<span class="f">IP Address</span>
#Html.EditorFor(model => model.TechnologyIP.IPAddress)
#Html.ValidationMessageFor(model => model.TechnologyIP.IPAddress)
<input type="CheckBox" name="IsTMSIPUnique" value="true" #(Html.Raw(Model.IsTMSMACUnique ? "checked=\"checked\"" : "")) /> IP Unique. |
<span class="f"> MAC Address</span>
#Html.EditorFor(model => model.TechnologyIP.MACAddress)
#Html.ValidationMessageFor(model => model.TechnologyIP.MACAddress)
<input type="CheckBox" name="IsTMSMACUnique" value="true" #(Html.Raw(Model.IsTMSMACUnique ? "checked=\"checked\"" : "")) /> MAC Unique.
</div>
<input type="submit" value="Save" class="btn btn-primary"/>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
but all the data annotation on the view model will not fire on the partial view , the AssignIps view model class is :-
namespace TMS.ViewModels
{
public class AssignIps
{
public TechnologyIP TechnologyIP { get; set; }
public bool IsTMSIPUnique { get; set; }
public bool IsTMSMACUnique { get; set; }
}
}
and he TechnologyIP model class is :-
namespace TMS.Models
{
[MetadataType(typeof(TechnologyIP_Validation))]
public partial class TechnologyIP
{}}
namespace TMS.Models
{
public class TechnologyIP_Validation
{
[Required]
public string IPAddress { get; set; }
but the [Required] data annotation on the TechnologyIP model, will not fire on the partial view,, can anyone adovce please?
Thanks.
Sections defined in your layout view don't get populated when using PartialViewResult, so the unobtrusive validation scripts are not being added.
You can test this by creating an action on your controller that just returns a partial view, and then call this via $.get() (using jQuery, obviously). If you use console.log(), you can inspect the result in Firebug. You could also use something like Fiddler; regardless, if you look at the HTML returned you will not see the script references anywhere.
Exactly, a wrong practice is to have:
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
in the partial view, try to do it just putting
#Scripts.Render("~/bundles/jqueryval")
and it should work!

asp net mvc3 post a list of objects to action

I created a page with aspnet mvc3. It show all users info as a list. I want to do something with this list. There are some checkboxes that belong to each items. When I click some checkboxes and press submit button, I want to post the whole list as a collection and save each items of this collection to database. There are several notes on internet but there is no exact solution. I have a UserDto. and want to use this to transfer users data in all sections.
Does anyone have any full solution about this or can they give any idea?
Thanks in advance.
Kerem
I added some of my codes. You can see the lead sentences what they are about.
this is my index view detail:
#model List<DomainModel.UserApprovalDto>
#{
ViewBag.Title = "Manage Users";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>
Manage Users</h2>
<div>#Html.Partial("_PartialManageUsers", (List<DomainModel.UserApprovalDto>)Model) </div>
this is my partial view detail:
#model List<DomainModel.UserApprovalDto>
#using (Html.BeginForm("ConfirmUsers", "ManageUsers", FormMethod.Post))
{
<table>
<tr>
<th>
Name
</th>
<th>
Is Reported
</th>
</tr>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => Model[i].FirstName)
</td>
<td>
#Html.CheckBox("IsReported", Model[i].IsReported.HasValue ? Model[i].IsReported.Value : false)
#*#Html.CheckBoxFor(modelItem => Model[i].IsReported.Value);*# #* #if (Model[i].IsReported != null)
{
#Html.CheckBoxFor(modelItem => Model[i].IsReported.Value);
}
else
{
#Html.CheckBoxFor(modelItem => Model[i].IsReported.Value);
}*#
</td>
<td>
</td>
</tr>
}
</table>
<div>
<input name="submitUsers" type="submit" value="Save" />
</div>
}
this is my controller submit method
[HttpPost]
public ActionResult ConfirmUsers(List<DomainModel.UserApprovalDto> collection)
{
if (ModelState.IsValid)
{
//TO-DO
}
return RedirectToAction("Index");
}
this last one is my DTO class detail:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DomainModel
{
public class UserApprovalDto
{
public long UserId { get; set; }
public Guid CarUserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhotoPath { get; set; }
public string PhotoSmallPath { get; set; }
public string PhotoSquarePath { get; set; }
public string PhotoBigPath { get; set; }
public bool IsBlocked { get; set; }
public bool IsDeleted { get; set; }
}
}
when I submit this code my list return null collection to my controller method.
thanks for your comments.
Assuming you are creating a screen which adds/ remove users to a course. So let's create some viewmodels
public class CourseVM
{
public string Name { set;get;}
public int CourseID { set;get;}
public List<UserVM> Users { set;get;}
public CourseVM()
{
Users=new List<UserVM>();
}
}
public class UserVM
{
public string Name { set;get;}
public int UserID{ set;get;}
public bool IsSelected { set;get;}
}
Now in your GET Action, you will fill the values of the ViewModel and sent it to the view.
public ActionResult Add()
{
var vm = new CourseVM();
//The below code is hardcoded for demo. you may replace with DB data.
vm.Users.Add(new UseVM { Name = "Jon" , UserID=1});
vm.Users.Add(new UseVM { Name = "Scott", UserID=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(UserVM.cshtml)
Add this code to 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 CourseVM
#using (Html.BeginForm())
{
<div>
#Html.EditorFor(m=>m.Users)
</div>
<input type="submit" value="Submit" />
}
Now when you post the form, Your Model will have the Users Collection where the Selected Checkboxes will be having a True value for the IsSelected Property.
[HttpPost]
public ActionResult Add(CourseVM model)
{
if(ModelState.IsValid)
{
//Check for model.Users collection and Each items
// IsSelected property value.
//Save and Redirect(PRG pattern)
}
return View(model);
}

ASP.NET MVC3: Interaction between Partial View and Main View

I have a partial view for contact. Currently the index view shows this partial view for contact details. There is a save button inside the partial view to save the edited data. There is a validation for age while saving the edited data. This much is working fine.
Whenever user edit age and save it, I need to show the corresponding horoscope prediction on the main view. How do we achieve it?
public class ContactEntity
{
public int ContactID { get; set; }
public string ContactName { get; set; }
[Range(18, 50, ErrorMessage = "Must be between 18 and 50")]
public int ContactAge { get; set; }
}
public class AgeHoroscope
{
public int Age { get; set; }
public string HoroscopePrediction { get; set; }
}
//Home Controller
namespace MYContactEditPartialViewTEST.Controllers
{
public class HomeController : Controller
{
List<AgeHoroscope> horoList = new List<AgeHoroscope>()
{
new AgeHoroscope{Age=16,HoroscopePrediction="You are confused"},
new AgeHoroscope{Age=26,HoroscopePrediction="You are very brilliant"},
new AgeHoroscope{Age=27,HoroscopePrediction="You are practical"}
};
public ActionResult Index()
{
AgeHoroscope selectedHoro = horoList[1];
return View(selectedHoro);
}
}
}
//Contact Controller
namespace MYContactEditPartialViewTEST.Controllers
{
public class ContactController : Controller
{
public PartialViewResult MyContactDetailEdit()
{
Thread.Sleep(500);
return PartialView(GetContact());
}
[HttpPost]
public PartialViewResult MyContactDetailEdit(string conatcclick)
{
//Save to database
Thread.Sleep(500);
return PartialView(GetContact());
}
private ContactEntity GetContact()
{
ContactEntity contactEntity = new ContactEntity();
contactEntity.ContactID = 1;
contactEntity.ContactName = "Lijo";
contactEntity.ContactAge = 26;
return contactEntity;
}
}
}
//Index.cshtml
#model MYContactEditPartialViewTEST.AgeHoroscope
#{
ViewBag.Title = "Index";
}
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<h2>
Index</h2>
<div>
<a>Your age is <b>#Html.DisplayFor(x => x.Age) </b>and the prediction is <b>" #Html.DisplayFor(x => x.HoroscopePrediction)
" </b></a>
<br />
</div>
<div style="border: 3px solid Teal">
#Html.Action("MyContactDetailEdit", "contact")
</div>
// MyContactDetailEdit.cshtml
#model MYContactEditPartialViewTEST.ContactEntity
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<h3>MyContactDetailEdit PARTIAL</h3>
<div>
#Html.HiddenFor(x => x.ContactID)
<br />
<div style="font-weight:bold">
Name:
<br />
</div>
#Html.DisplayFor(x => x.ContactName)
<br />
<br />
<div style="font-weight:bold">
Age
<br />
</div>
#Html.EditorFor(x => x.ContactAge)
#Html.ValidationMessageFor(model => model.ContactAge)
<br />
<br />
</div>
<input type="submit" id="saveButton" value="Save" />
}
READING
ASP.Net MVC Passing multiple parameters to a view
ASP.Net MVC 3 RC2, Partial Views Form Handling
I would like just use jQuery to do ajax post and then change the parent view client side directly
you'll need to create a new ViewModel to do this. This ViewModel (IndexViewModel.cs) would look something like this (I'm guessing at this):
public class IndexViewModel
{
public int ContactID { get; set; }
public string ContactName { get; set; }
public int ContactAge { get; set; }
public string HoroscopePrediction { get; set; }
}
you'd then use it in your controller index action (and view):
#model MYContactEditPartialViewTEST.IndexViewModel
the idea being that you'd populate the HoroscopePrediction in a join between ContactEntity and AgeHoroscope (or via Linq etc) and thus show each line in the index as a complete object (showing contact and horoscope).
As data is posted to "HomeController" and "Index" action, so changes are reflected when you change age in View.
Try to modify the home controller as follows,then it will work as expected.
1) Instead of having a list of AgeHoroscope, we can have a dictionary of age and prediction.
2) Create two Index Action for HttpGet and HttpPost as follows.
public class HomeController : Controller
{
Dictionary<int, string> AgePred = new Dictionary<int, string>()
{
{16,"You are confused"},
{26,"You are very brilliant"},
{27,"You are practical"}
};
[HttpGet]
public ActionResult Index()
{
AgeHoroscope selectedHoro = new AgeHoroscope() { Age = 26 };
selectedHoro.HoroscopePrediction = AgePred[selectedHoro.Age];
return View(selectedHoro);
}
[HttpPost]
public ActionResult Index(AgeHoroscope model,ContactEntity entity)
{
model.Age = entity.ContactAge;
model.HoroscopePrediction = AgePred[entity.ContactAge];
return View(model);
}
}

Resources