How to bind Model Fields inside another Model in the Controller? - c#

I have a Model (Register.cs) that contains 2 other Model (ProfileMeta ,ProfileDetail) as fields. How do I bind these 2 Model fields in my Controller class? When I name my 2 field objects the same as the Model file names, as I've seen. When I reference them in ProfileController, they're seen as types and not objects.
Error 26 An object reference is required for the non-static field, method, or property 'ContosoUniversity.Models.ProfileMeta.password.get' C:\Projects\DatingSite\datingSite\ContosoUniversity\Controllers\ProfileController.cs 63 40 DatingSiteInitial
However, when I rename them to different names, and refer them like so in ProfileController, I get the compilation error below:
" doesn't exist in the current context"
Models/Register.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ContosoUniversity.Models
{
public class Register
{
public ProfileMeta ProfileMeta { get; set; }
public ProfileDetail ProfileDetail { get; set; }
}
}
Controllers/ProfileController.cs:
// POST: Profiles/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ProfileMeta,ProfileDetail")] Register register)
{
if (ModelState.IsValid)
{
//Add 1 ProfileMeta row and 1 linked ProfileDetail row
ProfileMeta profileMeta = new ProfileMeta();
//How to refer to bound: ProfileMeta, ProfileDetail fields inside Register.cs?
profileMeta.Username = ProfileMeta.Username;
profileMeta.password = ProfileMeta.password;
profileMeta.ID = ProfileDetail.ID;
db.ProfileDetails.Add(ProfileDetail);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(profileDetail);
}
Views/Profile/Create.cshtml:
#model ContosoUniversity.Models.Register
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Profile</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ProfileMeta.Username, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ProfileMeta.Username, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProfileMeta.Username, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ProfileMeta.password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ProfileMeta.password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProfileMeta.password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ProfileDetail.Age, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ProfileDetail.Age, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProfileDetail.Age, "", new { #class = "text-danger" })
</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")
}

Related

View returns null to a controller, accepting ViewModel

I have a problem with my controller. It accepts null.
First of all I've got such ViewModel
public class FilmVM
{
public Film Film { get; set; }
public IEnumerable<Image> Images { get; set; } = new List<Image>();
public IEnumerable<SimilarFilm> SimilarFilms { get; set; } = new List<SimilarFilm>();
}
Controller looks like
public ActionResult Edit(FilmVM film)
{
_unitOfWork.Film.Update(film);
return RedirectToAction("Index");
}
Index action looks like
public ActionResult Index(int? page)
{
int pageSize = Constaints.Constaint.FilmsCount;
int pageNumber = page ?? 1;
var films = _unitOfWork.Film.GetDatas();
return View(films.ToPagedList(pageNumber, pageSize));
}
Models in VM are defaults like Guid, name, etc.
View model looks like
#model GuessTheMovieApp.ViewModels.FilmVM
#{
ViewBag.Title = "Edit";
}
<div class="wrapper">
<h2>Edit</h2>
#using (Html.BeginForm("Edit", "Films", FormMethod.Post, new { #class = "form-edit-film" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Editing Film</h4>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.Partial("EditFilm", Model.Film)
<div class="form-group">
<div class="form-group__input">
<input type="submit" value="Save" class="btn btn-success" />
</div>
</div>
</div>
}
</div>
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Partial View looks like
#model GuessTheMovieApp.Models.DataBase.Film
<div class="form-horizontal">
<h4>Film</h4>
<hr />
#Html.HiddenFor(model => model.FilmId)
<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>
<div class="form-group">
#Html.LabelFor(model => model.Year, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Year, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Year, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Genre, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Genre, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Genre, "", new { #class = "text-danger" })
</div>
</div>
</div>
they are common, I think.
I saw similar question on stackoverflow, but it didn't helped me. So I'm asking if someone knows an answer on such question, please help.
UPD
Figured out how to work with this by changing Action Edit to this format
public ActionResult Edit(Film films, IEnumerable<Image> images, IEnumerable<SimilarFilm> similarFilms)
{
_unitOfWork.Film.Update(new FilmVM { Film = films, Images = images, SimilarFilms = similarFilms });
_unitOfWork.Save();
return RedirectToAction("Index");
}
I don't think you can prevent your controller from accepting null at the parameter level, the best you can do is to do a null check on the object coming in before you call your _unitofWork
try to use the same model for view, partial view and action. You can use FilmVm as well as any another model. For example you can use Film in this case
#model GuessTheMovieApp.ViewModels.Film
.....
<partial name="EditFilm" />
......
and action
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Film film)
{
var filmVm= new FilmVm { Film=film}
.....
}

StackOverflowException is caused by a default mvc view

I created a simple create view for a model by mvc's automated way to show to a coleague.
Now, although i do not really use that, i can't see where a recursion is caused since i just said to mvc to create it for a model where all the fields are made with the
"public 'type' 'name' { get; set;}" format. I will include the model, action, and view below.
This isn't really a problem for me since i do not use the templates at all but I am curious how this could happen when no custom code was inserted
Thanks in advance
Controller Action
public ActionResult View()
{
return View();
}
Model
namespace Data_Access.Models
{
public class StudentModel
{
public int studentId { get; set; }
public string name { get; set; }
public string surname { get; set; }
public string classroom { get; set; }
public string role { get; set; }
public string imgPath { get; set; }
}
}
And finally the View
#model Data_Access.Models.StudentModel
#{
ViewBag.Title = "View";
}
<h2>View</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>StudentModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.studentId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.studentId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.studentId, "", new { #class = "text-danger" })
</div>
</div>
<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>
<div class="form-group">
#Html.LabelFor(model => model.surname, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.surname, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.surname, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.classroom, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.classroom, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.classroom, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.role, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.role, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.role, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.imgPath, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.imgPath, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.imgPath, "", new { #class = "text-danger" })
</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>
The controller has infinite recursion:
public ActionResult View()
{
return View();
}
Your View() method calls the same View() method ;)
Probably naming problem - I can't suggest any solution here, because you didn't take any information about the flow, what should be implemented in controller.
You can change action name to ViewPage() and add route attribute Route[("View")] above the action.
example:
[Route("View")]
public IActionResult ViewPage()
{
return View();
}
then rename View.cshtml to ViewPage.cshtml
This will prevent recursive and you also use url path /View
I hope this will help you.

C# MVC can't retrieve data from view to controller [duplicate]

This question already has answers here:
Asp.Net MVC: Why is my view passing NULL models back to my controller?
(2 answers)
Closed 4 years ago.
I am new to ASP.Net and I am sure this is a very basic question. I have a employee crud views . In create view i was created viewModel to pass different two model . One Model display emloyee and another model connect to db and retrieve all departments to my view . But I can't retrieve data to my employee create controller area. Vs send this err Abc.Models.MyViewModel.Employee.get returned null. On Debug.Print(employee.Employee.Name) line.
Here my Models ;
Employee.cs
public class Employee
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Surname { get; set; }
[Required]
public string phoneNumber { get; set; }
public string Detail { get; set; }
//Bu kısımda veri tabanı ilişkisi 1 to many olacak
public int DepartmentId { get; set; }
public Department Department { get; set; }
}
Department.cs
public class Department
{
public int Id { get; set; }
public string depName { get; set; }
public List<Employee> Employees { get; set; }
}
MyViewModel.cs
public class MyViewModel
{
public Employee Employee { get; set; }
public IEnumerable<Department> departments { get; set; }
}
I added dropboxlist on my create.cshtml area with MyViewModel and i can't retrieve all data on my controller .
Here my EmployeeController.cs ;
// GET: Employee/Create
[HttpGet]
public ActionResult Create()
{
MyViewModel viewModel = new MyViewModel();
Employee emp = new Employee();
viewModel.Employee = emp;
viewModel.departments = db.Departments;
return View(viewModel);
}
// POST: Employee/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(/*[Bind(Include = "Id,Name,Surname,phoneNumber,Department,Detail")]*/ MyViewModel employee)
{
//string emName = employee.Employee.Name;
Debug.Print(employee.Employee.Name);
if (ModelState.IsValid)
{
db.Employees.Add(employee.Employee);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
Here Create.cshtml "this html codes are in #using (Html.BeginForm()");
#model TelefonRehberi.Models.MyViewModel
<div class="form-horizontal">
<h4>Employee</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Employee.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Employee.Surname, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee.Surname, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee.Surname, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Employee.phoneNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee.phoneNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee.phoneNumber, "", new { #class = "text-danger" })
</div>
</div>
<!--Dropdown List Olacak-->
<div class="form-group">
#Html.LabelFor(model => model.Employee.Department, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<!--Burada zorlandım umarım doğru kullanım olmuştur.-->
#Html.DropDownListFor(m => m.Employee.Department, new SelectList(Model.departments.Select(i => i.depName)), " - Select or Add -", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Employee.Department, "", new { #class = "text-danger" })
</div>
</div>
<!--Dropdown List Sonu Ayarlamalar Yapılacak.-->
<div class="form-group">
#Html.LabelFor(model => model.Employee.Detail, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee.Detail, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee.Detail, "", new { #class = "text-danger" })
</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>
Add Form and try to do
#using (Html.BeginForm("ActionName","ControllerName", FormMethod.Post))
{
<div class="form-horizontal">
<!--add your other code here -->
<!--add your other code here -->
<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>
}
HTML Forms are required, when you want to collect some data from the site visitor. For example, during user registration you would like to collect information such as name, email address, credit card, etc.
A form will take input from the site visitor and then will post it to a back-end application such as CGI, ASP Script or PHP script etc. The back-end application will perform required processing on the passed data based on defined business logic inside the application.
There are various form elements available like text fields, textarea fields, drop-down menus, radio buttons, checkboxes, etc.
Ok, you were really close. In Create method you need to create Employee employee and not MyViewModel employee. So in controller just put this Create method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Employee employee)
{
Debug.Print(employee.Name);
if (ModelState.IsValid)
{
//db.Employees.Add(employee);
//db.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
Then binding will work just fine and you will get your employee from the form.
Just in case bellow is also the code for the form in the Create View.
<h2>Create</h2>
#using (Html.BeginForm("Create", "Employee", FormMethod.Post))
{
<div class="form-horizontal">
<h4>Employee</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Employee.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Employee.Surname, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee.Surname, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee.Surname, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Employee.phoneNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee.phoneNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee.phoneNumber, "", new { #class = "text-danger" })
</div>
</div>
<!--Dropdown List Olacak-->
<div class="form-group">
#Html.LabelFor(model => model.Employee.Department, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<!--Burada zorlandım umarım doğru kullanım olmuştur.-->
#Html.DropDownListFor(m => m.Employee.Department, new SelectList(Model.departments.Select(i => i.depName)), " - Select or Add -", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Employee.Department, "", new { #class = "text-danger" })
</div>
</div>
<!--Dropdown List Sonu Ayarlamalar Yapılacak.-->
<div class="form-group">
#Html.LabelFor(model => model.Employee.Detail, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee.Detail, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee.Detail, "", new { #class = "text-danger" })
</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>
}

How to realize Edit method with 2 models in 1 View

The beginning of my topic is here.
Using DropDownList dont allow me to edit Author`s name.. But that solution is really good.
I need to edit all 4 fields like name, title, year and price.
I try to make something like composite model:
public class BookAuthorCompositeModel
{
public Author author { get; set; }
public Book book { get; set; }
}
Change my get method:
// GET: Books/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return HttpNotFound();
}
var compModel = new BookAuthorCompositeModel();
compModel.book = dbBooks.Books.ToList().Where(a => a.Id == id).SingleOrDefault();
compModel.author = dbBooks.Authors.ToList().Where(x => x.Id == id).SingleOrDefault();
return View(bookEdit);
}
and it displays all I need (i tap "edit" and see information about name, title, year and price).
My view is:
#model BookStorage.Models.BookAuthorCompositeModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Book</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.book.Id)
<div class="form-group">
#Html.LabelFor(model => model.author.AuthorName, "AuthorName", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.author.AuthorName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.author.AuthorName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.book.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.book.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.book.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.book.YearPublish, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.book.YearPublish, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.book.YearPublish, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.book.Price, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.book.Price, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.book.Price, "", new { #class = "text-danger" })
</div>
</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")
}
but something wrong is in Post method:
[HttpPost]
public ActionResult Edit(Book book)
{
if (ModelState.IsValid)
{
dbBooks.Entry(BAmodel.book).State = EntityState.Modified;
dbBooks.Entry(BAmodel.author).State = EntityState.Modified;
dbBooks.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
dbBooks.SaveChanges(); leads to error (Store update, insert, or delete statement affected an unexpected number of rows (0).). I think using this kind of ViewModel helps to edit all rows, but it doesn't send data to DB, and I can't understand what is wrong.
If I understood correctly, what you want is to update a context "Book" and a context "Author" at the same API method.
To do so, first I would make a ViewModel that contains both objects, which you already have:
public class BookAuthorCompositeModel
{
public Author author { get; set; }
public Book book { get; set; }
}
(This can be modified for validation purposes, maybe creating new objects for validation. At least, I did it like that. But let's go on.)
Now, you need to receive that same ViewModel on your API call, and then do what you need with the objects. To do so, I usually do a Get call on my context, obtaining the object to be modified. Then I'm free to update my context:
[HttpPost]
public ActionResult Edit(BookAuthorCompositeModel model)
{
...
}
To get the object to be modified, depends on what you are using. Simple repository pattern, Unit pattern, doesn't matter. When you get the Book entry, just modify it, use Update function, which I belive to be dbBooks.BookContext.Update(book), where "book" is variable. Something like this:
var book = dbBooks.BooksContext.Get(model.Book.BookId);
book.name = "New Name";
dbBooks.BooksContext.Update(book);
dbBooks.SaveChanges();
The method for getting and updating ( .Get() and .Update() ) must be the ones from the pattern that you are using, but maybe this can help you.
Good luck!

Razor populating drop down list

On my page I want to include a list of members in a drop down list but I am not sure how exactly I could do this.
How would I populate a drop down list with the members that I am passing with the controller?
This is my controller
//Add Event
public ActionResult CreateEvent()
{
var members = db.ClubMembers.ToList();
return View(members);
}
//Add Event
[HttpPost]
public ActionResult CreateEvent(ClubEvent incomingEvent)
{
try
{
if (ModelState.IsValid)
{
using (var db = new UltimateDb())
{
db.ClubEvents.Add(incomingEvent);
db.SaveChanges();
}
return RedirectToAction("Index");
}
return View();
}
catch
{
return View();
}
}
This is the view I will be using
#model ultimateorganiser.Models.ClubEvent
#{
ViewBag.Title = "CreateEvent";
}
<h2>CreateEvent</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>ClubEvent</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#*Event Title*#
<div class="form-group">
#Html.LabelFor(model => model.EventTitle, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EventTitle, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EventTitle, "", new { #class = "text-danger" })
</div>
</div>
#*Event Description*#
<div class="form-group">
#Html.LabelFor(model => model.EventDesc, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EventDesc, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EventDesc, "", new { #class = "text-danger" })
</div>
</div>
#*Event Type*#
<div class="form-group">
#Html.LabelFor(model => model.eventType, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EnumDropDownListFor(model => model.eventType, htmlAttributes: new { #class = "form-control", #id = "dropdown" })
#Html.ValidationMessageFor(model => model.eventType, "", new { #class = "text-danger" })
</div>
</div>
#*Add People*#
#*<div class="form-group">
Add Members
<div class="col-md-10">
Drop Down List of members will go here
</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>
}
The best way to pass data between views and action methods are view models.We will go that way.
First create a new view model for the create view.
public class CreateEventVm
{
public string EventDescription {set;get;}
public List<SelectListItem> Members {set;get;}
public int MemberId {set;get;}
}
and in your GET action
public ActionResult Create()
{
var vm = new CreateEventVm();
var db= new UltimateDb();
vm.Members =db.Members.Select(s=> new SelectListItem
{ Value=s.Id.ToString(),
Text = s.Name
}).ToList();
return View(vm);
}
And your create razor view which is strongly typed to our new CreateEventVm
#model CreateEventVm
#using(Html.BeginForm())
{
<label>Description</label>
#Html.TextBoxFor(s=>s.EventDescription)
<label>Member</label>
#Html.DropDownListFor(s=>s.MemberId,Model.Members,"Select one")
<input type="submit" />
}
And in your HttpPost action method
[HttpPost]
public ActionResult Create(CreateEventVm model)
{
if(ModelState.IsValid)
{
using (var db = new UltimateDb())
{
var event = new ClubEvent();
event.EventDescription = model.EventDescription;
//Set other properties also from view model.
db.ClubEvents.Add(event);
db.SaveChanges();
}
// Redirect to another action after successful save (PRG pattern)
return RedirectToAction("SavedSuccessfully");
}
vm.Members =db.Members.Select(s=> new SelectListItem
{ Value=s.Id.ToString(),
Text = s.Name
}).ToList();
return View(vm);
}

Categories