cannot convert between an Identity Class and a local one in ASP.net MVC - c#

I'm currently developing with ASP.NET MVC and after I have created the an error of converting a local class to an Identity one cannot implicitly convert "ListUsers" to "Identity.IdentityUser"(I simplified the error a bit) anyway, here are some bits of code:
ListUsersController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ServiceReferenceAuthentication;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using SoftSMS.Data.Data;
using SoftSMS.Data.Entities;
using SoftSMS.Data.Entity;
using SoftSMS.Data.Interfaces;
using SoftSMS.MVC.ViewModels;
namespace SoftSMS.MVC.Controllers
{
public class ListUsersController : Controller
{
private readonly DataContext _context;
private readonly RoleManager<IdentityRole> roleManager;
private readonly UserManager<ListUsers> userManager;
private readonly IConfiguration configuration;
private readonly IUnitOfWork<ListUsers> _users;
//private readonly DataContext _context;
public ListUsersController(IUnitOfWork<ListUsers> Users/*DataContext context*/)
{
_users = Users;
//_context = context;
}
// GET: ListUsers
public IActionResult Index()
{
return View(_users.Entity.GetAll());
}
// GET: ListUsers/Details/5
public async Task<IActionResult> DetailsAsync(Guid? id)
{
if (id == null)
{
return NotFound();
}
...
if (listUsers == null)
{
return NotFound();
}
return View(listUsers);
}
// GET: ListUsers/Create
public IActionResult Create()
{
return View();
}
// POST: ListUsers/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 async Task<IActionResult> Create([Bind("Id,UserName,FirstName,LastName,Status,Profil")] ListUsers listUsers)
{
try
{
TPFAuthenticationSoapClient.EndpointConfiguration endpointConfiguration = new TPFAuthenticationSoapClient.EndpointConfiguration();
TPFAuthenticationSoapClient servAuth = new TPFAuthenticationSoapClient(endpointConfiguration);
if ((Boolean)TempData["isValid"] == false)
{
IdentityUser u = await userManager.FindByNameAsync(listUsers.UserName);
if (u != null)
{
ViewBag.IsValid = false;
ModelState.AddModelError(string.Empty, "Ce Compte existe déja");
}
else
{
...;
if (x != null)
{
...
return View(listUsers);
}
else
{
...
}
}
}
else
{
...
return RedirectToAction(nameof(Index));
}
return View(listUsers);
}
catch (Exception ex)
{
...
return RedirectToAction(nameof(Create));
}
}
the error is in IdentityUser u = await userManager.FindByNameAsync(listUsers.UserName);
I don't want to create an operator override as it's suggested (nor explicit conversion),
ListUsers.cs:
using Microsoft.AspNet.Identity.EntityFramework;
using SoftSMS.Data.Entities;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
namespace SoftSMS.Data.Entity
{ public enum StatusType
{ Banned,Registered,Normal,Warned}
public enum ProfilType
{ Admin,Manager,Agent}
public class ListUsers : IdentityUser
{
[DataType(DataType.Text)]
public string FirstName { get; set; }
[DataType(DataType.Text)]
public string LastName { get; set; }
[DataType(DataType.Text)]
[Required]
public StatusType Status { get; set; }
public ProfilType Profil { get; set; }
public virtual ICollection<MembershipAssociations> MembershipAssociation { get; set; }
public virtual ICollection<Template> TemplateNavigation { get; set; }
public virtual ICollection<SentMsg> SentmsgNavigation { get; set; }
}
}
UsersViewModel.cs:
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace SoftSMS.MVC.ViewModels
{ public enum StatusType
{ Banned,Registered,Normal,Warned}
public enum ProfilType
{ Admin,Manager,Agent}
public class UsersViewModel : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public StatusType Status { get; set; }
public ProfilType Profil { get; set; }
public List<MembershipAssociationViewModel> MembershipAssociation { get; set; }
public List<SentMsgViewModel> Sentmsg { get; set; }
}
}
and Create.cshtml:
#model SoftSMS.MVC.ViewModels.UsersViewModel
#{ ViewData["Title"] = "Create"; }
#{TempData["isValid"] = ViewBag.isValid;}
<br />
<h3>Nouvel Utilisateur</h3>
<hr />
#*#ViewBag.Result1*#
<br />
<h4 style="color: red;">#TempData["errorMessage"]</h4>
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
#if ((Boolean)ViewBag.isValid == false)
{
<div class="form-group">
<label asp-for="UserName" class="control-label">Login</label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div> }
#if ((Boolean)ViewBag.isValid == true)
{
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="UserName" class="control-label">Login</label>
<input asp-for="UserName" class="form-control" disabled="disabled" />
#Html.HiddenFor(model => model.UserName)
</div>
<div class="form-group">
<label asp-for="FirstName" class="control-label">Prenom</label>
<input asp-for="FirstName" class="form-control" disabled="disabled" />
#Html.HiddenFor(model => model.FirstName)
</div>
<div class="form-group">
<label asp-for="LastName" class="control-label">Nom</label>
<input asp-for="LastName" class="form-control" disabled="disabled" />
#Html.HiddenFor(model => model.LastName)
</div>
<div class="form-group">
<label asp-for="Email" class="control-label">Email</label>
<input asp-for="Email" class="form-control" disabled="disabled" />
#Html.HiddenFor(model => model.Email)
</div>
<div class="form-group">
<label asp-for="EstActif" class="control-label">Actif</label>
<select id="Select1" asp-for="EstActif" class="form-control">
<option value="True"> <text>OUI</text></option>
<option value="False"> <text>NON</text></option>
</select>
</div> }
<div class="form-group">
<input type="submit" value="Creer" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Liste des utilisateurs</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
as you could have seen, I had to make the UI in French (even though I don't like it) because I am developing this platform for French people,
if you need another resource, I could share it, but not the entire app, the ...is for a confidential code,
thank you

Related

ASP.NET Core Razor Pages Form Input Validation Not Working

So, I am developing a theoretically simple enough questionnaire application with user accounts and I am trying to validate the user input. For example here I am trying to make the First name field Required. I have followed some tutorials and it should be simple but I must be missing something. When I check if my model state is valid to reload the page or post the data, I get an error message telling me that the fields are required even though I have provided a value for them. I have removed some unimportant code parts for clarity. What seems to be the problem here?
CreateAdmin.cshtml
#page
#model ResumePostingService.Pages.CRUD.CreateAdminModel
#{
ViewData["Title"] = "Create Admin";
Layout = "~/Pages/SharedPages/_Layout_Admin.cshtml";
}
<div>
<h2>#Model.Messages</h2>
</div>
<h2>Add a new Admin Record</h2>
<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="Admin.FirstName" class="control-label">First Name</label>
<input type="text" asp-for="Admin.FirstName" class="form-control" />
<span asp-validation-for="Admin.FirstName" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-success" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="/Admin_Pages/Admin_Index" class="btn btn-danger">Cancel</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
CreateAdmin.cshtml.cs
namespace ResumePostingService.Pages.CRUD
{
public class CreateAdminModel : PageModel
{
private readonly ResumePostingService.Models.ResumePostingServiceDatabaseContext _context;
public CreateAdminModel(ResumePostingService.Models.ResumePostingServiceDatabaseContext context)
{
_context = context;
}
readonly DataAccessClass objadmin = new DataAccessClass();
[BindProperty]
public Admin Admin { get; set; }
public string Messages { get; set; }
public IActionResult OnGet()
{
if (HttpContext.Session.GetInt32("Admin Id") == null)
{
return RedirectToPage("/SharedPages/Unauthorized");
}
else
{
return Page();
}
}
public ActionResult OnPost()
{
if (!ModelState.IsValid)
{
Messages = string.Join("; ", ModelState.Values
.SelectMany(x => x.Errors)
.Select(x => x.ErrorMessage));
return Page();
}
objadmin.AdAddAdmin(Admin);
return RedirectToPage("/Admin_Pages/Admin_Index", new { actres = 4 });
}
}
}
Admin.cs
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ResumePostingService.Models
{
public partial class Admin
{
public Admin()
{
}
[Key]
public int AdminId { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Please enter the name")]
[StringLength(20, MinimumLength = 2, ErrorMessage = "Password cannot be longer than 20 characters and less than 2 characters")]
public string FirstName { get; set; }
}
}

How to fix "Required" annotation not working in .NET

I'm following this tutorial: https://learn.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/validation?view=aspnetcore-2.2
Here's my movie model class:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class Movie
{
public int ID { get; set; }
[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
[RegularExpression(#"^[A-Z]+[a-zA-Z""'\s-]*$")]
[Required]
[StringLength(30)]
public string Genre { get; set; }
}
But when I test it on my local, these two fields: Title and Genre don't seem to have the validation that I was expecting, see screenshot below:
Here's my controller form of actions:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Models.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Models.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Here's my Create.cshtml:
#page
#model RazorPagesMovie.Pages.Movies.CreateModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Movie</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="Movie.Title" class="control-label"></label>
<input asp-for="Movie.Title" class="form-control" />
<span asp-validation-for="Movie.Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.ReleaseDate" class="control-label"></label>
<input asp-for="Movie.ReleaseDate" class="form-control" />
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Genre" class="control-label"></label>
<input asp-for="Movie.Genre" class="form-control" />
<span asp-validation-for="Movie.Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.Price" class="control-label"></label>
<input asp-for="Movie.Price" class="form-control" />
<span asp-validation-for="Movie.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-page="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Here's my folder structure:
At first I thought there might be a sequence of validation, but actually after I filled out Release Date and Price, I was able to create a movie even without filling in Title and Genre. So apparently the validation for these two fields didn't work.
Could anyone share any insight please?
Thanks!
your required field is never null it is empty string and you must prevent your field from being passed by empty strings like this :
[StringLength(60, MinimumLength = 3)]
[Required(AllowEmptyStrings =false)]
public string Title { get; set; }
For required field validation decorate your function with [BindRequired(ErrorMessage = "Title Required")] instead of using [Required(ErrorMessage="Title Required")]

View post form return null?

I am having problems to return a model using a form.
The problem is when I submit the form, the values are null even though I've specified that returns a model
This is my controller
And this is my View that returns null.
#model MyEnglishDictionary.Models.Dictionary
#{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<form method="post" asp-action="Create">
<div class="p-4 border rounded">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group row">
<div class="col-2">
<label asp-for="Word"></label>
</div>
<div class="col-5">
<input asp-for="Word" class="form-control" />
</div>
<span asp-validation-for="Word" class="text-danger"></span>
</div>
<div class="form-group row">
<div class="col-2">
<label asp-for="Meaning"></label>
</div>
<div class="col-5">
<input asp-for="Meaning" class="form-control" />
</div>
<span asp-validation-for="Meaning" class="text-danger"></span>
</div>
<div class="form-group row">
<div class="col-2">
<label asp-for="Pronunciation"></label>
</div>
<div class="col-5">
<input asp-for="Pronunciation" class="form-control" />
</div>
<span asp-validation-for="Pronunciation" class="text-danger"></span>
</div>
<br />
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Create" />
<a asp-action="Index" class="btn btn-success">Back To List</a>
</div>
</div>
</form>
#section Scripts{
#{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
EDIT
This is my Dictionary controller.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using MyEnglishDictionary.Data;
using MyEnglishDictionary.Models;
namespace MyEnglishDictionary.Controllers
{
public class DictionaryController : Controller
{
private readonly ApplicationDbContext _db;
public DictionaryController(ApplicationDbContext db)
{
_db = db;
}
public IActionResult Index()
{
return View(_db.Dictionaries.ToList());
}
public IActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Models.Dictionary word)
{
if(!ModelState.IsValid)
{
return View(word);
}
_db.Add(word);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
}
}
And this is my Dictionary model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MyEnglishDictionary.Models
{
public class Dictionary
{
[Key]
public int Id { get; set; }
[Required]
public string Word { get; set; }
[Required]
public string Meaning { get; set; }
[Required]
public string Pronunciation { get; set; }
public string Link { get; set; }
public DateTime Date { get; set; }
}
}
I am using Net Core 2.1, but I have some few projects that I use the same way to pass the form model from View to controller and they work.
You need to pay attention to the name of the parameter and fields.
For your issue, it is caused by that you defined a field which is Word and the parameter is word which caused the binding failed.
Try to change the public async Task<IActionResult> Create(Models.Dictionary word) to public async Task<IActionResult> Create(Models.Dictionary dictionary).
change the word parameter name to something else like _word, it seems like the compiler doesn't accept it as a parameter name in c#.
public async Task<IActionResult> Create(Models.Dictionary _word)
{
if(!ModelState.IsValid)
{
return View(_word);
}
_db.Add(_word);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
btw, I didn't see it in the reserved keywords list
You have to bind the properties to your model. In your case:
public async Task<IActionResult> Create([Bind("Word, Meaning, Pronounciation")] Dictionary word)
Further reading:
Model Binding

Facing Object reference not set exception even though operation succeeding [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 years ago.
I'm getting the following error each Time I try to enter a new Course.
Object reference not set to an instance of an object.
AspNetCore._Views_Admin_Manage_cshtml+<b__23_12>d.MoveNext()
in Manage.cshtml, line 34
Here is my Controller:
using ASP_Project.Data;
using ASP_Project.Models;
using ASP_Project.Services.Interfaces;
using ASP_Project.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace ASP_Project.Controllers
{
public class AdminController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SchoolContext _schoolContext;
private readonly IAdminRepository _adminRepos;
private readonly ITeacherRepository _teacherRepository;
public AdminController(UserManager<ApplicationUser> userManager,
SchoolContext schoolContext,
IAdminRepository adminRepos,
ITeacherRepository teacherRepository
)
{
_userManager = userManager;
_schoolContext = schoolContext;
_adminRepos = adminRepos;
_teacherRepository = teacherRepository;
}
[HttpGet]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Index()
{
ClaimsPrincipal currentUser = User;
var user = await _userManager.GetUserAsync(currentUser);
var admin = _adminRepos.GetAdminByUser(user);
return View(new AdminViewModel()
{
FirstName = admin.FirstName,
LastName = admin.LastName,
MiddleName = admin.MiddleName
});
}
[HttpGet]
public IActionResult Manage()
{
IEnumerable<string> teachers = _teacherRepository.TeacherNames();
return View(new CourseViewModel()
{
Teachers = teachers
});
}
[HttpPost]
public async Task<IActionResult> Manage(CourseViewModel courseViewModel)
{
var teacher = _schoolContext.Teacher.Single(t => t.FirstName == courseViewModel.TeacherName);
Course course = new Course()
{
CodeID = courseViewModel.CodeID,
Name = courseViewModel.Name,
NumOfCredits = courseViewModel.NumOfCredits,
TeacherID = teacher.TeacherID
};
await _schoolContext.Course.AddAsync(course);
if (await _schoolContext.SaveChangesAsync() == 0)
return RedirectToAction("Index", "Admin");
return View(courseViewModel);
}
}
}
Here is my View:
#model ASP_Project.ViewModels.CourseViewModel
#{
ViewData["Title"] = "Manage";
}
<h2>Manage</h2>
<div class="row">
<div class="col-md-4">
<form asp-controller="Admin" asp-action="Manage" method="post" class="form-horizontal" role="form">
<h4>Create a new Course.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="CodeID"></label>
<input asp-for="CodeID" class="form-control" />
<span asp-validation-for="CodeID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name"></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="NumOfCredits"></label>
<input asp-for="NumOfCredits" class="form-control" />
<span asp-validation-for="NumOfCredits" class="text-danger"></span>
</div>
<div>
<label asp-for="TeacherName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="TeacherName" class="form-control" required>
<option value="" disabled selected>Select Teacher</option>
#foreach (var teach in Model.Teachers)
{
<option value="#teach"> #teach </option>
}
</select>
<span asp-validation-for="TeacherName" class="text-danger"></span>
</div>
</div>
<button type="submit" class="btn btn-default">Add</button>
</form>
</div>
</div>
#section Scripts {
#await Html.PartialAsync("_ValidationScriptsPartial")
}
My CourseViewModel:
using ASP_Project.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace ASP_Project.ViewModels
{
public class CourseViewModel
{
[Required]
public string CodeID { get; set; }
[Required]
public int NumOfCredits { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string TeacherName { get; set; }
public IEnumerable<string> Teachers { get; set; }
}
}
And Finally the Function used to retrieve the names of the teachers:
public IEnumerable<string> TeacherNames() => _schoolContext.Teacher.Select(t => t.FirstName);
What I understood from the exception is that there is either a part of the foreach that needs an await or that one of the Objects is not being defined.
Take note that the operation is doing its job successfully nonetheless and the data is being added to the database, its just that this strange exception keeps showing up.
Edit: Even though #NoCodeFound answer Pointed out that I should debug (and that's what I did to find the answer) yet I was planning on doing that anyway, and I happened to discover the real cause anyway.
Turns out I messed up when I return from the Manage action after POST, since I used:
if (await _schoolContext.SaveChangesAsync() == 0)
return RedirectToAction("Index", "Admin");
return View(courseViewModel);
which was making me go through the courseViewModel again rather than being redirected to the page I needed.
So the fix would simply be:
if (await _schoolContext.SaveChangesAsync() == 0)
return View(courseViewModel);
return RedirectToAction("Index", "Admin");

Edit View not passing data correctly

I'm trying to edit an element through the edit view. While debugging, I've noticed that the object I'm trying to update the database with has null or zeroed fields. The edit view seems to not return the data I'm entering.
Model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Infrastructure;
namespace METALIMPEX.Models
{
public class Condition
{
[Key]
[Display(Name = "Condition ID")]
[Column("condition_id")]
[Required]
public int conditionID { get; set; }
[Display(Name = "Date and time")]
[Column("condition_date")]
[Timestamp]
[Required]
public DateTime dateTime { get; set; }
[Display(Name = "Component ID")]
[Column("component")]
[Required]
public int componentID { get; set; }
[Display(Name = "Operator ID")]
[Column("operator")]
[Required]
public int operatorID { get; set; }
[Display(Name = "Component status")]
[Column("condition")]
[Required]
public bool condition { get; set; }
[Display(Name = "Comments")]
[Column("remarks")]
[Required]
public string comments { get; set; }
}
public class ConditionDBContext : DbContext
{
public DbSet<Condition> Conditions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=DELL-XPS\\SQLEXPRESS;Initial Catalog=METALIMPEX;Integrated Security=True");
}
}
}
Controller:
using System.Linq;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Data.Entity;
using METALIMPEX.Models;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Web;
using System;
namespace METALIMPEX.Controllers
{
public class ConditionController : Controller
{
private ApplicationDbContext _context;
private ConditionDBContext db = new ConditionDBContext();
IList<Condition> conditionList = new List<Condition>();
public ConditionController(ApplicationDbContext context)
{
_context = context;
//DEPRECATED CODE, MANUAL QUERY, PROJECT NOW USES DBCONTEXT
/*string strConnection = "Data Source=DELL-XPS\\SQLEXPRESS;Initial Catalog=METALIMPEX;Integrated Security=True";
string sqlQuery = "SELECT REPLICATE('0',6-LEN(RTRIM(PartID))) + RTRIM(PartID) AS 'Part ID', REPLICATE('0', 6 - LEN(RTRIM(OperatorID))) + RTRIM(OperatorID) AS 'Operator ID', Date_Time AS 'Time', IsPartWorking AS 'Part Status', IsMachineWorking AS 'Machine Status' FROM Defect";
SqlConnection sqlConnection = new SqlConnection(strConnection);
SqlCommand command = new SqlCommand(sqlQuery, sqlConnection);
SqlDataReader Dr;
try {
sqlConnection.Open();
Dr = command.ExecuteReader();
while (Dr.Read())
{
conditionList.Add(new Defect()
{
conditionID = Dr["Part ID"].ToString(),
operatorID = Dr["Operator ID"].ToString(),
dateTime = Dr["Time"].ToString(),
partStatus = (bool)Dr["Part Status"],
machineStatus = (bool)Dr["Machine Status"]
});
};
Dr.Dispose();
}
catch (SqlException) {
throw new InvalidOperationException("An error has occured while connecting to the database");
//OR
//return View("Error");
}*/
}
// GET: Condition
public IActionResult Index()
{
//return View(conditionList);
return View(db.Conditions.ToList());
}
// GET: Condition/Details/5
public IActionResult Details()
{
return View(conditionList);
}
// GET: Condition/Create
public IActionResult Create()
{
return View();
}
// POST: Condition/Create
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Condition condition)
{
if (ModelState.IsValid)
{
//_context.Condition.Add(condition);
//_context.SaveChanges();
return RedirectToAction("Index");
}
return View(condition);
}
// GET: Condition/Edit/5
public IActionResult Edit(int id)
{
if (conditionList == null)
{
return HttpNotFound();
}
Condition condition = db.Conditions.Single(m => m.conditionID == id);
return View(condition);
}
// POST: condition/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(Condition condition)
{
if (ModelState.IsValid)
{
db.Update(condition);
db.Entry(condition).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(condition);
}
// GET: condition/Delete/5
[ActionName("Delete")]
public IActionResult Delete(string id)
{
return View(conditionList);
}
// POST: condition/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public IActionResult DeleteConfirmed(string id)
{
/*Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
db.Movies.Remove(movie);
db.SaveChanges();
return RedirectToAction("Index");*/
return RedirectToAction("Index");
}
}
}
View:
#model METALIMPEX.Models.Condition
#{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<form asp-action="Edit">
<div class="form-horizontal">
<h4>Condition</h4>
<hr />
<div asp-validation-summary="ValidationSummary.ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="conditionID" />
<div class="form-group">
<label asp-for="componentID" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="componentID" class="form-control" />
<span asp-validation-for="componentID" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="operatorID" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="operatorID" class="form-control" />
<span asp-validation-for="operatorID" class="text-danger" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
<input asp-for="condition" />
<label asp-for="condition"></label>
</div>
</div>
</div>
<div class="form-group">
<label asp-for="dateTime" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="dateTime" class="form-control" />
<span asp-validation-for="dateTime" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="comments" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="comments" class="form-control" />
<span asp-validation-for="comments" 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>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
}
I'm a beginner in .NET so I have no real idea what's wrong here. The edit view was generated by the framework so I assume it should be working.
Any ideas?
The issue is with the parameter name of the Edit Action method. Below is the URL encoded form-data posted from the view on clicking Save button.
conditionID=&dateTime=2013-12-01&componentID=1&operatorID=1&condition=true&comments=
The action parameter name is condition and there is a key-value pair condition=true in the incoming form-data. The MVC model binding process will try to map the parameter/property(in case of complex model) name to the corresponding Route/Query String/Request Body data.
Hence it's trying to map the value of condition in the form-data i.e. true to the action parameter and eventually fails to convert bool to object.
Change the parameter name to any name that doesn't corresponds to any key name in the form-data and it should work.

Categories