For whatever reason I'm unable to Create and Edit using the ViewModel called CreateEmployeeViewModel that I created. I can however Create and Edit fine without using the CreateEmployeeViewModel but was told it was bad practive to use the main Models for CRUD. I am however able to retrieve values to my 2 DropDownList tags fine using the CreateEmployeeViewModel, just not Create or Edit. Below are my current Models, ViewModels, Controllers and Views.
I just figure out why I cannot Create using the public IActionResult Create(Employee employee) Active Method.
Employee Model: (located in Models folder)
public class Employee
{
[Key]
public int EmpId { get; set; }
[Required]
public string EmpFirstName { get; set; }
[Required]
public string EmpLastName { get; set; }
public int DeptId { get; set; }
public Department Department { get; set; }
public int BldgId { get; set; }
public Building Building { get; set; }
}
EmployeeController: (located in Controllers folder)
public class EmployeeController : Controller
{
private DataEntryContext _context;
public EmployeeController(DataEntryContext context)
{
_context = context;
}
public IActionResult Index()
{
return View(_context.Employees.ToList());
}
// Populate Department values to DropDownList
private IEnumerable<SelectListItem> GetDeptList()
{
var dept = _context.Departments
.Select(s => new SelectListItem
{
Value = s.DeptId.ToString(),
Text = s.DeptTitle
})
.ToList();
return (dept);
}
// Populate Building values to DropDownList
private IEnumerable<SelectListItem> GetBldgList()
{
var bldg = _context.Buildings
.Select(b => new SelectListItem
{
Value = b.BldgId.ToString(),
Text = b.BldgName
})
.ToList();
return (bldg);
}
public IActionResult Create()
{
CreateEmployeeViewModel model = new CreateEmployeeViewModel();
model.DeptList = GetDeptList();
model.BldgList = GetBldgList();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Employee employee)
{
if (ModelState.IsValid)
{
_context.Employees.Add(employee);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
public IActionResult Edit(int? id)
{
if (id == null)
{
return View("Error");
//return NotFound();
}
var employee = _context.Employees
.Where(e => e.EmpId == id)
.Single();
if (employee == null)
{
return View("Error");
//return NotFound();
}
return View(employee);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(Employee employee)
{
if (ModelState.IsValid)
{
_context.Employees.Update(employee);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
}
CreateEmployeeViewModel: (located in ViewModels Folder)
public class CreateEmployeeViewModel
{
public int EmpId { get; set; }
public string EmpFirstName { get; set; }
public string EmpLastName { get; set; }
public int DeptId { get; set; }
public IEnumerable<SelectListItem> DeptList { get; set; }
public int BldgId { get; set; }
public IEnumerable<SelectListItem> BldgList { get; set; }
}
Employee Create View:
<form asp-controller="employee" asp-action="Create" method="post" class="form-horizontal" role="form">
<div class="form-horizontal">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="EmpFirstName" class="col-md-2 control-label">First Name</label>
<div class="col-md-10">
<input asp-for="EmpFirstName" class="form-control" />
<span asp-validation-for="EmpFirstName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="EmpLastName" class="col-md-2 control-label">Last Name</label>
<div class="col-md-10">
<input asp-for="EmpLastName" class="form-control" />
<span asp-validation-for="EmpLastName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="DeptId" class="col-md-2 control-label">Department</label>
<div class="col-md-10">
<select asp-for="DeptId" asp-items="#Model.DeptList" class="form-control">
<option>Select Department</option>
</select>
<span asp-validation-for="DeptId" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="BldgId" class="col-md-2 control-label">Building Location</label>
<div class="col-md-10">
<select asp-for="BldgId" asp-items="#Model.BldgList" class="form-control">
<option>Select Building</option>
</select>
<span asp-validation-for="BldgId" class="text-danger"></span>
</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>
In your Create method, you are sending to the view the CreateEmployeeViewModel but in your HttpPost Create method you are accepting back the Employee model instead of the CreateEmployeeViewModel. So once you change the post methods signature to accept the correct CreateEmployeeViewModel, you can simply map it back to the Employee model.
Get Action Method:
public IActionResult Create(Employee employee)
{
return View(employee);
}
Just change in your Post Action Method:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(CreateEmployeeViewModel vm)
{
if (ModelState.IsValid)
{
var model = new Employee{
//your logic here for example
employeename = vm.employeename,
employeepassword = vm.employeepassword
}
_context.Employees.Add(model);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
and donĀ“t forget to cal View Model in your .cshtml
Related
I've made many to many relationship in ASP.NET Core and there are two tables Category and Subject
This is Category Model
public class Category
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public List<CategorySubject> CategorySubjects { get; set; } = new List<CategorySubject>();
}
This is subject model
public class Subject
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Exam_Time { get; set; }
public List<CategorySubject> CategorySubjects { get; set; }
}
This is CategorySubject Model
public class CategorySubject
{
public int CategoryId { get; set; }
public int SubjectId { get; set; }
public Category Category { get; set; }
public Subject Subject { get; set; }
}
This is part of DatabaseContext
public DbSet<CategorySubject> CategorySubjects { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<CategorySubject>().HasKey(pt => new { pt.CategoryId, pt.SubjectId });
modelBuilder.Entity<CategorySubject>().HasOne(pt => pt.Category)
.WithMany(pt => pt.CategorySubjects).HasForeignKey(p => p.CategoryId);
modelBuilder.Entity<CategorySubject>().HasOne(pt => pt.Subject)
.WithMany(pt => pt.CategorySubjects).HasForeignKey(p => p.SubjectId);
}
I made one helper class by the name of Helper
public class Helpers:Profile
{
public Helpers()
{
CreateMap<Subject, SubjectViewModel>().ReverseMap();
CreateMap<SubjectViewModel, Subject>();
CreateMap<Category, CategoryViewModel>().ReverseMap();
}
}
this is category service:
public void Insert(Category category)
{
_context.Categories.Add(category);
}
public void Update(Category category)
{
_context.Categories.Update(category);
}
This is CategoryController :
// GET: CategoryController/Create
public IActionResult Create()
{
var subjectFromRepo = _categorySubject.Subject.GetAll();
var selectList = new List<SelectListItem>();
foreach (var item in subjectFromRepo)
{
selectList.Add(new SelectListItem(item.Name, item.Id.ToString()));
}
var vm = new CategoryViewModel()
{
Subjects = selectList
};
return View(vm);
}
// POST: CategoryController/Create
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(CategoryViewModel vm )
{
try
{
Category category = new Category()
{
Name = vm.Name
};
foreach(var item in vm.SelectedSubjects)
{
category.CategorySubjects.Add(new CategorySubject()
{
SubjectId = Int32.Parse(item)
});
}
_categorySubject.Category.Insert(category);
_categorySubject.Save();
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
// GET: CategoryController/Edit/5
public IActionResult Edit(int id)
{
var category = _categorySubject.Category.GetCategoryById(id);
var subjects = _categorySubject.Subject.GetAll();
var selectsubjects = category.CategorySubjects.Select(x => new Subject()
{
Id = x.Subject.Id,
Name = x.Subject.Name
});
var selectlist = new List<SelectListItem>();
subjects.ForEach(i => selectlist.Add(new SelectListItem(i.Name, i.Id.ToString(),
selectsubjects.Select(x => x.Id).Contains(i.Id))));
var vm = new CategoryViewModel()
{
Id= category.Id,
Name = category.Name,
Subjects = selectlist
};
return View(vm);
}
// POST: CategoryController/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(CategoryViewModel vm)
{
try
{
var category = _categorySubject.Category.GetCategoryById(vm.Id);
category.Name = vm.Name;
var selectedSubjects = vm.SelectedSubjects;
var existingSubjects = category.CategorySubjects.Select(x => x.SubjectId.ToString()).ToList();
var toAdd = selectedSubjects.Except(existingSubjects).ToList();
var toRemove = existingSubjects.Except(selectedSubjects).ToList();
var CategorySubjects = category.CategorySubjects.Where(x => !toRemove.Contains(x.SubjectId.ToString())).ToList();
foreach (var item in toAdd)
{
category.CategorySubjects.Add(new CategorySubject()
{
SubjectId = Int32.Parse(item),
CategoryId = Int32.Parse(item)
});
}
_categorySubject.Save();
return RedirectToAction("Index", "Category");
}
catch
{
return View();
}
}
This is Create.cshtml of Category :
<div class="style-form">
<h2 class="text-center mt-3 mb-lg-3">Create New Category</h2>
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="row">
<div class="col-md-3 col-lg-3 col-sm-3"></div>
<div class="col-md-6 col-lg-6 col-sm-6">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><strong>Name:</strong></span>
</div>
<input asp-for="Name" class="form-control input-hover" placeholder="Enter Name.." />
<span asp-validation-for="Name" class="text-danger"></span>
</div><br />
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><strong>Subject:</strong></span>
</div>
<select asp-for="SubjectId" class="form-control input-hover" asp-items="#Model.Subjects ">
<option value="">Please choose a Subject...</option>
</select>
<span asp-validation-for="SubjectId" class="text-danger"></span>
</div><br />
</div>
</div>
<div class="row">
<div class="col-md-3 col-lg-3 col-sm-3"></div>
<div class="col-md-6 col-lg-6 col-sm-6">
<div class="form-group">
<button type="button" class="btn btn-backToList">
<a asp-action="Index">Back to List</a>
</button>
<button type="submit" class="btn btn-create">Create</button>
</div>
</div>
</div>
</form>
There when I click on the create new category button I can get data of subject form drop down list, but when I want to submit it I face this error:
NullReferenceException: Object reference not set to an instance of an object.
AspNetCore.Views_Category_Create.b__20_0() in Create.cshtml, line 27
<select asp-for="SubjectId" class="form-control input-hover" asp-items="#Model.Subjects ">
I think there is an exception thrown in the Create (POST) method, it then goes to the catch, which returns a view without a model
catch
{
return View();
}
The next exception comes while rendering the page trying to bind to #Model.Subjects where Model is null.
Remove try/catch or handle the catch to find if there is any exception.
I'm creating a simple MVC project for my ASP.NET classes at the Uni.
It consists of one model class (BikeAds), Controller (BikeAdsController) and Views (Create, Delete, Details, Edit, Index) and uses mdf file as a database.
Controller and views were generated automatically (I chose "MVC controller with views, using Entity Framework").
I encountered the problem when trying to create a new entry. When I fill the "Create" form and click "Submit" button, it clears all data from the input fields and the form is not submitted - validation doesn't allow for empty fields. When I removed [Required] validation, I got a SQL exception (null is not allowed in the database).
I do not understand where the cause of the issue my lie.
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using bikes_ads.Data;
using bikes_ads.Models;
namespace bikes_ads.Controllers
{
public class BikeAdsController : Controller
{
private readonly BikesAdvertsDbContext _context;
public BikeAdsController(BikesAdvertsDbContext context)
{
_context = context;
}
// GET: BikeAds
public async Task<IActionResult> Index()
{
return View(await _context.Adverts.ToListAsync());
}
// GET: BikeAds/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var bikeAd = await _context.Adverts
.FirstOrDefaultAsync(m => m.Id == id);
if (bikeAd == null)
{
return NotFound();
}
return View(bikeAd);
}
// GET: BikeAds/Create
public IActionResult Create()
{
return View();
}
**// POST: BikeAds/Create
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id")] BikeAd bikeAd)
{
if (ModelState.IsValid)
{
_context.Add(bikeAd);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(bikeAd);
}**
// GET: BikeAds/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var bikeAd = await _context.Adverts.FindAsync(id);
if (bikeAd == null)
{
return NotFound();
}
return View(bikeAd);
}
// POST: BikeAds/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id")] BikeAd bikeAd)
{
if (id != bikeAd.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(bikeAd);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!BikeAdExists(bikeAd.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(bikeAd);
}
// GET: BikeAds/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var bikeAd = await _context.Adverts
.FirstOrDefaultAsync(m => m.Id == id);
if (bikeAd == null)
{
return NotFound();
}
return View(bikeAd);
}
// POST: BikeAds/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var bikeAd = await _context.Adverts.FindAsync(id);
_context.Adverts.Remove(bikeAd);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool BikeAdExists(int id)
{
return _context.Adverts.Any(e => e.Id == id);
}
}
}
Create form:
#model bikes_ads.Models.BikeAd
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>BikeAd</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Category" class="control-label"></label>
<input asp-for="Category" class="form-control" />
<span asp-validation-for="Category" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ShortDescription" class="control-label"></label>
<input asp-for="ShortDescription" class="form-control" />
<span asp-validation-for="ShortDescription" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="LongDescription" class="control-label"></label>
<input asp-for="LongDescription" class="form-control" />
<span asp-validation-for="LongDescription" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="SellerName" class="control-label"></label>
<input asp-for="SellerName" class="form-control" />
<span asp-validation-for="SellerName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="SellerPhoneNumber" class="control-label"></label>
<input asp-for="SellerPhoneNumber" class="form-control" />
<span asp-validation-for="SellerPhoneNumber" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Model class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace bikes_ads.Models
{
public class BikeAd
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(50)]
public string Title { get; set; }
[Required]
public string Category { get; set; }
[Required]
[MaxLength(100)]
public string ShortDescription { get; set; }
[Required]
[MaxLength(500)]
public string LongDescription { get; set; }
[Required]
public string SellerName { get; set; }
[Required]
public string SellerPhoneNumber { get; set; }
[Required]
public double Price { get; set; }
public BikeAd(int id, string title, string category, string shortDescription, string longDescription, string sellerName, string sellerPhoneNumber, double price)
{
Id = id;
Title = title;
Category = category;
ShortDescription = shortDescription;
LongDescription = longDescription;
SellerName = sellerName;
SellerPhoneNumber = sellerPhoneNumber;
Price = price;
}
public BikeAd()
{
}
}
}
In your HTTPPost Create method, you're only binding the Id property;
public async Task<IActionResult> Create([Bind("Id")] BikeAd bikeAd)
{
}
Looking at your create form, you have other properties besides Id.
1) Shouldn't you be binding the all the other properties?
and
2) Shouldn't Id be automatically generated?
Change your Create method to this;
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Title,Category,Description,ShortDescription,LongDescription,SellerName,SellerPhoneNumber,Price")] BikeAd bikeAd)
{
if (ModelState.IsValid)
{
_context.Add(bikeAd);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(bikeAd);
}
I have two models:
public class Question
{
public int Id { get; set; }
public string Title { get; set; }
public int ClosedReasonId { get; set; }
public CloseReasonType CloseReasonType { get; set; }
}
public class CloseReasonType
{
public int Id { get; set; }
public string Name { get; set; }
public List<Question> Questions { get; set; }
}
I would like to create a view which has a form for adding questions and a dropdown for CloseReasonType.
#page
#model RazorPagesQuestion.Pages.Questions.CreateModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Question</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Question.Title" class="control-label"></label>
<input asp-for="Question.Title" class="form-control" />
<span asp-validation-for="Question.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Question.CloseReasonType" class="control-label"></label>
<select asp-for="Question.CloseReasonType" class="form-control"
asp-items="Model.CloseReasonType">
</select>
<span asp-validation-for="Question.CloseReasonType" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
Of course when I just added asp-items="Model.CloseReasonType" to my select tag helper it didn't populate the dropdown with options. How can I populate the options?
I added this to my CreateModel class
[BindProperty]
public Question Question { get; set; }
[BindProperty]
public List<SelectListItem> CloseReasonType { get; }
All the examples I have seen show how to create the list out of hardcoded values.
The full class:
public class CreateModel : PageModel
{
private readonly RazorPagesQuestion.Data.RazorPagesQuestionContext _context;
public CreateModel(RazorPagesQuestion.Data.RazorPagesQuestionContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Question Question { get; set; }
[BindProperty]
public List<SelectListItem> CloseReasonType { get; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Question.Add(Question);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
You would need to populate the select list for it to display on the page
Assuming your DbContext has a CloseReasonTypes property
//...
private void loadCloseReasonTypes() {
CloseReasonTypes = new SelectList(_context.CloseReasonTypes, nameof(CloseReasonType.Id), nameof(CloseReasonType.Name));
}
public IActionResult OnGet() {
loadCloseReasonTypes();
return Page();
}
public SelectList CloseReasonTypes { get; set; }
[BindProperty]
public Question Question { get; set; }
//...
Update the view to bind to the relevant property on the model.
<div class="form-group">
<label asp-for="Question.CloseReasonId" class="control-label">Close Reason</label>
<select asp-for="Question.CloseReasonId" class="form-control"
asp-items="Model.CloseReasonTypes">
</select>
<span asp-validation-for="Question.CloseReasonId" class="text-danger"></span>
</div>
The list will also need to be repopulated if the post was not successful as the page will reload, clearing the select list.
public async Task<IActionResult> OnPostAsync() {
if (!ModelState.IsValid) {
loadCloseReasonTypes();
return Page();
}
_context.Question.Add(Question);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
How can I use Two different models into the same view?
Why I need this?
I need to do a create view where the client fills his registry, and I need to have 1 combo box/select form(This form needs to load the strings from the other model).
Here is what I have tried:
Creating a ViewModel for both of the Models that looks like this:
public class CandidateViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public int Number { get; set; }
public string Profile { get; set; }
public Byte[] CV { get; set; }
public string CVNAME { get; set; }
public List<Profile> ProfileList { get; set; }
public string ProfileText { get; set; }
}
ProfileList and ProfileText are from ProfileModel, the rest is from the CandidateModel.
My controller right now looks like this:
public IActionResult Candidate(Candidate candidate, string searchString)
{
using (var aplicationDbContext = new ApplicationContext())
{
var candidates = from m in aplicationDbContext.Candidates select m;
if (!String.IsNullOrEmpty(searchString))
{
candidates = candidates.Where(s => s.Name.Contains(searchString) || s.Number.ToString().Contains(searchString) || s.ProfileText.Contains(searchString));
}
return View(candidates.ToList());
}
}
public IActionResult CandidateCreate()
{
using (var applicationcontext = new ApplicationContext())
{
var ProfileTextFromProfile = applicationcontext.Candidates.Include(q => q.ProfileList);
return View(ProfileTextFromProfile);
}
return View();
}
[HttpPost, ActionName("CandidateCreate")]
[ValidateAntiForgeryToken]
public IActionResult CandidateCreatePost([Bind("Name,Number,Profile,CV,CVID")] Candidate candidate, IFormFile CV,string profileText, int Id)
{
if (ModelState.IsValid)
{
if (CV != null)
{
if (CV.Length > 0)
{
byte[] p1 = null;
using (var fs1 = CV.OpenReadStream())
using (var ms1 = new MemoryStream())
{
fs1.CopyTo(ms1);
p1 = ms1.ToArray();
}
candidate.CVNAME = CV.FileName;
candidate.CV = p1;
}
}
using (var applicationcontext = new ApplicationContext())
{
var ProfileTextFromProfile = applicationcontext.Profile.Include(q => q.ProfileList);
//var ProfileTextFromProfile = applicationcontext.Profile.Include(q => q.ProfileText).Single(q => q.Id == Id);
//ProfileTextFromProfile.ProfileText.Add(new Candidate() { Profile = profileText });
}
candidateRepository.Add(candidate);
candidateRepository.SaveChanges();
return RedirectToAction("Candidate");
}
return View();
}
But I don't know what acctually I need to do after this, I'm really new to this and I'm doing this work as an intership soo I'm still learning, If have any doubts about my question please ask me and I will try to explain.
Also here is my View where I need to use both of the models.
#*model HCCBPOHR.Data.Candidate*#
#model HCCBPOHR.DomainModel.CandidateModel
#{
ViewData["Title"] = "CandidateCreate";
}
<h2>CandidateCreate</h2>
<h4>Candidate</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post" enctype="multipart/form-data" asp-action="CandidateCreate">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Number" class="control-label"></label>
<input asp-for="Number" class="form-control" maxlength="9" />
<span asp-validation-for="Number" class="text-danger"></span>
</div>
<div class="form-group">
<label>Selects</label>
<select asp-for="Profile" class=" form-control ">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
<div class="form-group">
<label asp-for="CV" type="file" class="control-label"></label>
<input asp-for="CV" type="file" class="form-control" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" onclick="this.disabled=true;this.form.submit();" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
You can apply MVVM pattern in this scenario.
Here is example:
I will define 3 class in Model folder
public class Post
{
public string Id {get;set;}
public string Content {get;set;}
public string UserId {get;set;}
}
public class Comment
{
public string Id {get;set;}
public string Content {get;set;}
public string PostId {get;set;}
}
// this will hold data for 2 class above
public class PostVM
{
public Post Post {get;set}
public Comment Comment {get;set}
}
Then in my controller I will query to db to get data for post and comment like this
public IActionResult PostDetail(string postId)
{
var post = _postRepository.GetPostById(postId);
var comment = _commentRepository.GetCommentByPostId(postId);
// MVVM model return to the view
var vM = new PostVM
{
Post = post,
Comment = comment
}
}
Finally in my view
#model PostVM
<div> #model.Post.Content </div>
#foreach(var comment in #model.Comment)
{
<div> #comment.Content</div>
}
Please adjust accordingly with your code. If you have any problem please let me know.
Cheers
I have two view models:
public class PersonViewModel
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Dob { get; set; }
public string Email { get; set; }
public ICollection<PetViewModel> Pets { get; set; }
}
public class PetViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public int PersonId { get; set; }
public PersonViewModel Person { get; set; }
}
When creating/editing a pet I want to have a drop down list of all the people to choose from. This is my pets controller:
\\ Other methods omitted for brevity
[HttpGet]
public IActionResult Create()
{
var people = _personService.AsQueryable().ToList();
ViewBag.PeopleList = new SelectList(people , "Id", "FirstName");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create([Bind("Id,Name,PersonId")] PetViewModel vm)
{
if (!ModelState.IsValid) return View(vm);
var pet = _petService.Create(vm.Name, vm.PersonId);
return RedirectToAction("Details", pet);
}
I am trying to do it via ViewBag and doing the following in the view as such:
#model UI.ViewModels.PetViewModel
<h2>Create</h2>
<form asp-action="Create">
<div class="form-horizontal">
<h4>Create a Pet</h4>
<div class="form-group">
<label asp-for="PersonId" class="col-md-2 control-label"></label>
<div class="col-md-10">
#Html.DropDownListFor(model => model.PersonId, ViewBag.PeopleList, "--Select--", new { #class = "form-control"})
<span asp-validation-for="PersonId" class="text-danger"></span>
</div>
</div>
</div>
</form>
Upon trying to do so I get the following error: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type.
Any help is appreciated. Thanks!
I managed to fix it by doing the following:
<div class="form-group">
<label asp-for="PersonId" class="col-md-2 control-label"></label>
<div class="col-md-10">
#Html.DropDownListFor(model => model.PersonId, (SelectList)ViewBag.PeopleList, "--Select--", new { #class = "form-control"})
<span asp-validation-for="PersonId" class="text-danger"></span>
</div>
</div>
I wasn't casting the ViewBag.PeopleList to a SelectList, changing the second parameter in my Html.DropDownList to (SelectList)ViewBag.PeopleList fixed the issue for me.