ASP.NET Core MVC : use remote input validation - asp.net-core-mvc

Edit 1: include full code related to this not just a portion.
I am trying to create username input validation for admin role on my application.
I will start from the table in SQL server.
Employee table columns in SQL server has [ROWID],[ID],[LAST_NAME],[FIRST_NAME]...
Employee DB model
public class EmployeeModel
{
public int RowID { get; set; }
[Key]
public int ID { get; set; }
public string First_Name { get; set; }
public string Last_Name { get; set; }
}
DB context
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext (DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<WorkOrderModel> WorkOrder { get; set; }
public DbSet<CommentModel> Comment { get; set; }
public DbSet<PostModel> Post { get; set; }
public DbSet<ReplyModel> Reply { get; set; }
public DbSet<ApplicationUser> ApplicationUser { get; set; }
public DbSet<EmployeeModel> Employee { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder); //This is necessary if class is IdentityDbContext instead of DbContext
modelBuilder.Entity<WorkOrderModel>().HasKey(c => new { c.Type, c.Base_ID, c.Lot_ID, c.Split_ID, c.Sub_ID });
}
}
My InputValidation controller is the controller that will only have remote validation logics in it.
I am trying to build a logic that will validate if the user is in the table "Employee" using only [ID] and [FIRST_NAME].
Original code I had is as below.
if (_dbContext.Employee.Any(n => (n.First_Name + "." + n.ID.ToString().PadLeft(3, '0')) == userName) != true)
{
return Json(true);
}
return Json($"Employee does not exist.");
Then changed to below per suggestion by Tisa in a reply.
public class InputValidationController : Controller
{
private readonly ApplicationDbContext _dbContext;
public InputValidationController(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
[AcceptVerbs("GET", "POST")]
public IActionResult IdVerification(string userName)
{
var allUserList = (from u in _dbContext.Employee
select new
{
Name = u.First_Name + "." + u.ID.ToString().PadLeft(3, '0')
})
.ToList().Where(x => x.Name == userName);
if (allUserList != null)
{
return Json(true);
}
return Json($"Employee does not exist.");
}
}
PageModel where input class is in.
public class ResetPasswordModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<ResetPasswordModel> _logger;
public ResetPasswordModel(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager, ILogger<ResetPasswordModel> logger)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
}
[BindProperty]
public InputModel Input { get; set; }
[TempData]
public string StatusMessage { get; set; }
public class InputModel
{
[Required]
[Display(Name = "User Name [ First Name.### (Employee number) ]")]
[Remote(action: "IdVerification", controller: "InputValidation")]
public string UserName { get; set; }
[Required]
[StringLength(20, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 3)]
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
//public string Code { get; set; }
}
...
}
Lastly the view page. SQL_Web_App is the name of the project and has UserRoles class.
#page
#model ResetPasswordModel
#using SQL_Web_App
#{
ViewData["Title"] = "Reset password";
}
#if (User.IsInRole(UserRoles.AdminRole))
{
<h1>#ViewData["Title"]</h1>
<h4>Reset password for a user.</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="Input.UserName"></label>
<input asp-for="Input.UserName" class="form-control" />
<span asp-validation-for="Input.UserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.ConfirmPassword"></label>
<input asp-for="Input.ConfirmPassword" class="form-control" />
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Reset</button>
</form>
</div>
</div>
}
my statement before this edit 1
As you can see under the display of the `InputModel` the user name is "FirstName.EmployeeNumber", I am trying to match that input to `_dbContext.Employee.Any(n => n.First_Name + "." + n.ID.ToString().PadLeft(3, '0')` but I do not get any result for both != and ==.
Now I tried below for both == and != result goes to always not null in any case.
if (allUserList != null)
{
Json(true);
}
return Json($"Employee does not exist.");
Please help me to see what I did wrong.
Thank you.
random name input but no validation message

You can change the logic to this:
To get the Name in your code, you should use Model to accept it and then get the
UserName property.
public IActionResult IdVerification(InputModel input)
{
var username=input.UserName;
var allUserList = (from u in _dbcontext.Employee
select new
{
Name = u.First_Name + "." + u.ID.ToString().PadLeft(3, '0')
})
.ToList();
if (allUserList[0].Name==userName)
{
return Json(true);
}
return Json($"Employee does not exist.");
}

Related

returning null value from populated selectlist with DB data

I'm implementing asp.net core MVC project. In my controller class called ApiApplicant, Create method, I have 3 selectlists that its items should be populated from a table called APIApplicantHistory. My models and create method and view are implemented like following:
using System.Collections.Generic;
namespace CSDDashboard.Models
{
public partial class Apiapplicant
{
public Apiapplicant()
{
ApiApplicantHistory = new HashSet<ApiApplicantHistory>();
}
public int Id { get; set; }
public string ApiRequestDate { get; set; }
public int? ApiRequestNo { get; set; }
public int? Apiid { get; set; }
public int? ApplicantId { get; set; }
public int? GateId { get; set; }
public string NocRequestDate { get; set; }
public string NocRequestNo { get; set; }
public string Url { get; set; }
public string Description { get; set; }
public bool? IsDeleted { get; set; }
public virtual Api Api { get; set; }
public virtual Applicant Applicant { get; set; }
public virtual Gate Gate { get; set; }
public virtual ICollection<ApiApplicantHistory> ApiApplicantHistory { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace CSDDashboard.Models
{
public partial class ApiApplicantHistory
{
public int Id { get; set; }
public int? ApiApplicantId { get; set; }
public string Date { get; set; }
public int? SentResponseType { get; set; }
public int? UnconfirmedReason { get; set; }
public int LastReqStatus { get; set; }
public string Description { get; set; }
public virtual Apiapplicant ApiApplicant { get; set; }
public virtual EntityType LastReqStatusNavigation { get; set; }
public virtual EntityType SentResponseTypeNavigation { get; set; }
public virtual EntityType UnconfirmedReasonNavigation { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace CSDDashboard.Models
{
public partial class EntityType
{
public EntityType()
{
ApiApplicantHistoryLastReqStatusNavigation = new HashSet<ApiApplicantHistory>();
ApiApplicantHistorySentResponseTypeNavigation = new HashSet<ApiApplicantHistory>();
ApiApplicantHistoryUnconfirmedReasonNavigation = new HashSet<ApiApplicantHistory>();
}
public int Id { get; set; }
public string Name { get; set; }
public string EntityKey { get; set; }
public virtual ICollection<ApiApplicantHistory> ApiApplicantHistoryLastReqStatusNavigation { get; set; }
public virtual ICollection<ApiApplicantHistory> ApiApplicantHistorySentResponseTypeNavigation { get; set; }
public virtual ICollection<ApiApplicantHistory> ApiApplicantHistoryUnconfirmedReasonNavigation { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CSDDashboard.Models
{
public class APIApplicantViewModel
{
public Apiapplicant apiApplicantvm { get; set; }
public ApiApplicantHistory apiApplicantHistoryvm { get; set; }
}
}
public class ApiapplicantsController : Controller
{
private readonly CSSDDashboardContext _context;
public ApiapplicantsController(CSSDDashboardContext context)
{
_context = context;
}
public IActionResult Create()
{
ViewData["sentResponseType"] = new SelectList(_context.EntityType.Where(g => g.EntityKey == "sentResponseType").ToList(), "ID", "name");
ViewData["unconfirmedReason"] = new SelectList(_context.EntityType.Where(g => g.EntityKey == "unconfirmedReason").ToList(), "ID", "name");
ViewData["lastReqStatus"] = new SelectList(_context.EntityType.Where(g => g.EntityKey == "lastRequestStatus").ToList(), "ID", "name");
return View();
}
}
And a part of create view implementation:
#model CSDDashboard.Models.APIApplicantViewModel
#{
ViewData["Title"] = "create";
}
<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="apiApplicantvm.GateId" class="control-label"></label>
<select asp-for="apiApplicantvm.GateId" class="form-control" asp-items="ViewBag.GateId"></select>
</div>
<div class="form-group">
<label asp-for="apiApplicantHistoryvm.SentResponseType" class="control-label"></label>
<select asp-for="apiApplicantHistoryvm.SentResponseType" class="form-control" asp-items="ViewBag.sentResponseType"></select>
</div>
<div class="form-group">
<label asp-for="apiApplicantHistoryvm.UnconfirmedReason" class="control-label"></label>
<select asp-for="apiApplicantHistoryvm.UnconfirmedReason" class="form-control" asp-items="ViewBag.unconfirmedReason"></select>
</div>
<div class="form-group">
<label asp-for="apiApplicantHistoryvm.LastReqStatus" class="control-label"></label>
<select asp-for="apiApplicantHistoryvm.LastReqStatus" class="form-control" asp-items="ViewBag.lastReqStatus"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
In create method, all the viewData are filled with the correct related data but the problem is existing in Create view, after running the project an error like below is shown in Create page:
An unhandled exception occurred while processing the request.
NullReferenceException: Object reference not set to an instance of an object.
After debugging the code I understand that In create view, apiApplicantvm is not null but apiApplicantHistoryvm returns null and the above error is because of that. I appreciate if anyone could tells me how to fix the problem.
I hope you would be using EF core as ORM because you are using Asp.net core.
To load related data in EF core.
It can be done in 2 ways or Lazy loading
Eager loading
_context.EntityType.Where(g=>g.EntityKey=="sentResponseType")
.Include(x=>x.ApiApplicantHistoryLastReqStatusNavigation).ToList()
OR
Lazy loading
on your modal creating
protected override void
OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder .UseLazyLoadingProxies() .UseSqlServer(myConnectionString);
OR
on startup.cs of your core MVC project
Lazy loading example.
.AddDbContext<BloggingContext>(
b => b.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString));
for more info learn.microsoft.com/en-us/ef/core/querying/related-data
https://learn.microsoft.com/en-us/ef/core/querying/related-data
Thank you very much for the answers. I'm using EF core and I changed my code as what you suggested. I added ViewData["sentResponseType"] = new SelectList(_context.EntityType.Where(g => g.EntityKey == "sentResponseType")
.Include(x => x.ApiApplicantHistoryLastReqStatusNavigation).ToList(), "ID", "name");
in my create method.
And my problem is here in Create view, in the below line there exists a null value in apiApplicantHistoryvm:
Thank you for the help. The problem was here in my code
ViewData["sentResponseType"] = new SelectList(_context.EntityType.Where(g => g.EntityKey == "sentResponseType").ToList(), "ID", "name");
I should use Id instead of ID according to my EntityType model.

Razor - Passing DropDownList selected value to Controller via Ajax.BeginForm

I am trying to pass the dropdownlist value to my controller so I can add the values to a list of paycodes but I keep getting a "Value cannot be null." error. My paycode list has many items in it. Not sure what is null or wrong here...
INNER EXCEPTION
Value cannot be null.
Parameter name: source
VIEW
<!-- products input-->
<div class="control-group col-lg-6">
<label class="control-label">Product</label>
<div class="controls">
#using (Ajax.BeginForm("AddPayCode", "Referral",
new AjaxOptions()
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "PayCodes",
Url = Url.Action("AddPayCode", "Referral")
}))
{
#Html.ValidationSummary()
#Html.DropDownListFor(model => model.SelectedPayCode, new SelectList(Model.PayCodes.ToList(), "Id", "Description"), "- Select -")
<input type="submit" value="Add" />
}
</div>
</div>
CONTROLLER
[HttpPost]
public void AddPayCode(ReferralModel model)
{
var test = model.SelectedPayCode;
//TODO: Add to model.Referral.PayCodes list and return list of selected items
}
MODEL
public class ReferralModel
{
public Customer Customer { get; set; }
public Employee Employee { get; set; }
public List<PayCode> PayCodes { get; set; }
public int SelectedPayCode { get; set; }
public Referral Referral { get; set; }
}
DOMAIN OBJECT
public class Referral
{
[Key]
public int Id { get; set; }
public int CustomerId { get; set; }
public int EmployeeId { get; set; }
public decimal Total { get; set; }
public virtual List<PayCode> PayCodes { get; set; }
public virtual Customer Customer { get; set; }
public virtual Employee Employee { get; set; }
}
Objective :
User chooses a paycode from the dropdown and clicks "Add" Paycode is
added to the referral PayCodes list
Controller returns the list of paycodes selected to the view (not
yet implemented)
The issue was the controller is missing the property of the dropdown list.
[HttpPost]
public void AddPayCode(ReferralModel model, ** string SelectedPayCode ** <-- missing)
{
var test = SelectedPayCode;
//TODO: Add to model.Referral.PayCodes list and return list of selected items
}

How send data from action method to view in MVC?

Expression in view
i have model in mvc name Flight :
public class Flight
{
public int id { get; set; }
[Required(ErrorMessage = "name is required")]
[StringLength(170)]
public string name { get; set; }
[Required(ErrorMessage = "flight company is required")]
[DisplayName("company Name")]
public string flightCompany { get; set; }
[DataType(DataType.Date)]
public DateTime date { get; set; }
public int idAvaribleClass { get; set; }
[DisplayName("Duration TO")]
public string flightDuration { get; set; }
[DisplayName("Ariport Name")]
[StringLength(200)]
public string airportName { get; set; }
public int idRegisterFlght { get; set; }
public List<FlightDuration> FlightDurations { get; set; }
public List<AvalibleClass> AvalibleClasses { get; set; }
public List<registerFlightProgram> registerFlightPrograms { get; set; }
}
i have action method which search in database about what is user enter in view and return two table by query linq.i want show this table in view :
_Mydb _db = new _Mydb();
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(string searchTerm = null, string to = null)
{
var q =
(from c in _db.flights
join p in _db.Durations on c.id equals p.FlightId
where (p.to == to) && (p.fromStar == searchTerm) && (to != null)
select new
{
c = new Flight { id = c.id, name = c.name, flightCompany = c.flightCompany, date = c.date, idAvaribleClass = c.idAvaribleClass, flightDuration = c.flightDuration, airportName = c.airportName, idRegisterFlght = c.idRegisterFlght },
p = new FlightDuration { id = p.id, fromStar = p.fromStar, to = p.to, takeOffTime = p.takeOffTime, expectedTime = p.expectedTime, priceDuration = p.priceDuration, FlightId =p.FlightId}
}).SingleOrDefault();
return View(q);
}
*code view , expression in "#foreach"*
#model IEnumerable<TourismPro.Models.Flight>
#{
ViewBag.Title = "Home Page";
}
#using (Html.BeginForm()){
<form method="post">
<input type="search" name="searchTerm" />
<input type="search" name="to" />
<input type="submit" value="Search By Name" />
**#foreach (var item in Model)**
{
<div>
#item.flightCompany
</div>
}
</form>
}

uploaded image Full Path in MVC3

I am uploading a file in MVC3 my csHtml page is
<div class="editor-label">
#Html.LabelFor(model => model.Resume)
</div>
<div class="editor-field">
<input type="file" name="Resume" id="Resume" />
#* #Html.EditorFor(model => model.ImageData)*#
#Html.ValidationMessageFor(model => model.Resume)
</div>
My Post Method is
[HttpPost]
public ActionResult SignUp(UserView user)
{
try
{
if (ModelState.IsValid)
{
UserManager userManager = new UserManager();
if (!userManager.IsUserLoginIDExist(user.LoginID))
{
// Request.Params["Resume"];
userManager.Add(user,Request.Files["Resume"]);
FormsAuthentication.SetAuthCookie(user.FirstName, false);
return RedirectToAction("Welcome", "Home");
}
}
}
catch
{
return View(user);
}
return View(user);
}
and my Model is
public class UserView
{
[Required]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[Display(Name = "Contact Number")]
public string ContactNumber { get; set; }
[Required]
[Display(Name = "Login ID")]
public string LoginID { get; set; }
[Required]
[Display(Name = "Password")]
public string Password { get; set; }
[Required]
[Display(Name = "Resume")]
public string Resume { get; set; }
}
}
I am getting user.Resume's value as full path(C:\test.png) on some machine and on some machine i am getting just name of the file(test.png). Please help me to deal with this miscellaneous issue
You aren't actually saving the file there at the moment. Perhaps you know this and have left the code out for brevity, but ASP.Net's built-in file handling gives you everything you need.
This question gives you all the info you need: File Upload Asp.net Mvc3.0

MVC 3 Selectlist/DropDownList Is Not Updating My Model

I hope someone can help with this one. I have three Model classes like this:
public class Provider
{
public Guid ProviderId { get; set; }
public string Name { get; set; }
public Guid LocationId { get; set; }
public virtual Location Location { get; set; }
}
public class Location
{
public Guid LocationId { get; set; }
public string NameOrCode { get; set; }
public string Description { get; set; }
public string StreetNumber { get; set; }
public string StreetAddress1 { get; set; }
public string StreetAddress2 { get; set; }
public string City { get; set; }
public int? StateId { get; set; }
public string Zip { get; set; }
public string ContactPhone { get; set; }
public virtual State State { get; set; }
}
public class State
{
public int StateId { get; set; }
public string Name { get; set; }
public string Abbreviation { get; set; }
}
As you can see, a Provider has a Location (separate class for reuse elsewhere), and a Location has a State (which is null until selected).
My Controller looks like this for my Create methods:
public class ProviderController : BaseController
{
private SetupContext db = new SetupContext();
// other CRUD methods ...
//
// GET: /Provider/Create
public ActionResult Create()
{
Location location = new Location()
{
LocationId = Guid.NewGuid(),
NameOrCode = Resources.BillingLocation,
Description = Resources.BillingLocationDescription
};
Provider provider = new Provider()
{
ProviderId = Guid.NewGuid(),
LocationId = location.LocationId,
Location = location
};
ViewBag.StateId = new SelectList(db.States, "StateId", "Name", provider.Location.StateId);
return View(provider);
}
//
// POST: /Provider/Create
[HttpPost]
public ActionResult Create(Provider provider)
{
if (ModelState.IsValid)
{
db.Locations.Add(provider.Location);
db.Providers.Add(provider);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.StateId = new SelectList(db.States, "StateId", "Name", provider.Location.StateId);
return View(provider);
}
// other CRUD methods ...
}
Finally, my View looks like this:
<div class="editor-label">
#Html.LabelFor(model => model.Location.StateId, #Resources.Location_State_Display_Name)
</div>
<div class="editor-field">
#Html.DropDownList("StateId", #Resources.ChooseFromSelectPrompt)
#Html.ValidationMessageFor(model => model.Location.StateId)
</div>
My problem is that the state the user selects in the DropDownList never gets set on my Model on the Create POST. I have similar code in my Edit View and the state is populated correctly in that View (that is, the state associated with an existing Provider.Location shows selected in the DropDownList for the user to edit if desire), but in both the Create and the Edit Views the selection made by the user is never registered in my Model (specifically the Provider.Location.StateId) coming in from the POST.
Looking at the HTML produced I see this:
<div class="editor-label">
<label for="Location_StateId">State/Territory</label>
</div>
<div class="editor-field">
<select id="StateId" name="StateId"><option value="">[Choose]</option>
<option value="1">Alabama</option>
<option value="2">Alaska</option>
<!-- more options ... -->
</select>
<span class="field-validation-valid" data-valmsg-for="Location.StateId" data-valmsg-replace="true"></span>
</div>
I suspect I need to somehow convey the Location.StateId relationship instead of just StateId as I see above but I can't figure out the correct syntax to do that. I've tried changing my ViewBag dynamic property to Location_StateId like this:
ViewBag.Location_StateId = new SelectList(db.States, "StateId", "Name", provider.Location.StateId);
And the DropDownList in my View like this:
#Html.DropDownList("Location_StateId", #Resources.ChooseFromSelectPrompt)
I figured then perhaps that notation would work because the label beside my DropDownList was rendered as:
<div class="editor-label">
<label for="Location_StateId">State/Territory</label>
</div>
This attempt did not work. Can you help me out?
Thanks in advance.
#Html.DropDownList("Location.StateId", #Resources.ChooseFromSelectPrompt)
Also the following line doesn't do anything useful:
ViewBag.StateId = new SelectList(db.States, "StateId", "Name", provider.Location.StateId);
You are assigning a SelectList to something that is supposed to be a scalar property. You probably wanted to pass the collection as ViewBag:
ViewBag.States = new SelectList(db.States, "StateId", "Name", provider.Location.StateId);
and then in the view:
#Html.DropDownList("Location.StateId", (SelectList)ViewBag.States)

Resources