I am getting HTTP ERROR 404 Exception in Edit Action - c#

Here is the code for Edit:
[HttpGet]
public async Task<IActionResult> Edit(string id)
{
var roles = _roleManager.Roles.ToList();
ViewBag.Roles = new SelectList(roles, "Id", "Name");
ApplicationUser user = await _userManager.FindByIdAsync(id);
if (user == null)
{
ViewBag.ErrorMessage = $"User with Id = {id} cannot be found";
return NotFound();
}
var userRole = _userManager.GetRolesAsync(user).ToString();
var userViewModel = new EditUserViewModel
{
UserId=user.Id,
Username=user.UserName,
FirstName=user.FirstName,
LastName=user.LastName,
Email=user.Email,
UserPIN=user.UserPIN,
Address=user.Address,
TelephoneNumber=user.PhoneNumber,
Roles = userRole
};
return View(userViewModel);
}
[HttpPost]
public async Task<IActionResult> Edit(EditUserViewModel userViewModel)
{
var user = await _userManager.FindByIdAsync(userViewModel.UserId);
if (user == null)
{
ViewBag.ErrorMessage = $"User with Id = {userViewModel.UserId} cannot be found";
return NotFound();
}
else
{
user.UserName = userViewModel.Username;
user.FirstName = userViewModel.FirstName;
user.LastName = userViewModel.LastName;
user.Email = userViewModel.Email;
user.UserPIN = userViewModel.UserPIN;
user.Address = userViewModel.Address;
user.PhoneNumber = userViewModel.TelephoneNumber;
var result = await _userManager.UpdateAsync(user);
_dbContext.SaveChanges();
if (result.Succeeded)
{
return RedirectToAction("Index");
}
foreach (var error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
return View(userViewModel);
}
}
This is my view model for Edit:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace Project.Models.UserViewModels
{
public class EditUserViewModel
{
public string UserId { get; set; }
[Required]
[StringLength(50, MinimumLength = 6,
ErrorMessage = "Username cannot be shorter than 6 characters and longer than 50.")]
public string Username { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(10, MinimumLength = 10,
ErrorMessage = "User PIN must be 10 characters long")]
public string UserPIN { get; set; }
[Required]
[StringLength(10, MinimumLength = 10,
ErrorMessage = "Telephone number must be 10 characters long")]
public string TelephoneNumber { get; set; }
[Required]
public string Address { get; set; }
[Required]
public string Roles { get; set; }
}
}
And this is my View:
#model Project.Models.UserViewModels.EditUserViewModel
<h1>Edit User</h1>
<div class="col-md-4">
<form asp-action="Edit" asp-controller="Admin" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="FirstName"> First name</label>
<input asp-for="FirstName" class="form-control" />
<span asp-validation-for="FirstName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="LastName"> Last name</label>
<input asp-for="LastName" class="form-control" />
<span asp-validation-for="LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Username"> Username</label>
<input asp-for="Username" class="form-control" />
<span asp-validation-for="Username" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="UserPIN">User PIN</label>
<input asp-for="UserPIN" class="form-control" />
<span asp-validation-for="UserPIN" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TelephoneNumber"></label>
<input asp-for="TelephoneNumber" class="form-control" />
<span asp-validation-for="TelephoneNumber" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Roles">Role</label>
<select asp-for="Roles" class="form-control" asp-items="#ViewBag.Roles"></select>
<span asp-validation-for="Roles" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address">Address</label>
<input asp-for="Address" class="form-control" />
<span asp-validation-for="Address" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
<div>
<a asp-action="Index">Back to User list</a>
</div>
I create an asp.net core application using Identity. Now I am customizing the project. I wrote AddUser and role and Delete Actions and they are working.
I get HTTP ERROR 404 exception when I try to edit my user in UserList.
I add _dbContext.SaveChanges(), but it is still not working. The rest CRUD operations are working properly like I said earlier.

The code that saves your model depends on the presence of the userViewModel.UserId information. But this is not present in the .cshtml code. So when the model is passed back to the controller in the HttpPost there is no data and the _userManager.FindByIdAsync will not find any user. The fix is simple, just add somewhere in the .cshtml an hidden field for the UserId
<form asp-action="Edit" asp-controller="Admin" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div> <input asp-for="UserId" class="d-none" /></div>
....
It is an hard fact to remember that the istance of the ViewModel passed to the view from the HttpGet action is not the same instance passed back to the HttpPost action. It is a new ViewModel instance and it is populated from the fields present in the View. If you forget a field then there is no value in the model passed back to the post action.

You have a fairly explicit error there in that 404 NotFound.
There's either a mismatch between how you're creating and storing the user, or in how you're attempting to retrieve it from _userManager, particularly:
_userManager.FindByIdAsync(userViewModel.UserId)
When debugging the Edit action, does the view model property UserId have a value?
If so, does the value match what UserId is set to when the user is created?
Either modify the data at creation, or supply more data during editing, to create a succesful match

Related

ASP.NET Core MVC : retrieve DateTime from database into view

I'm quite new to ASP.NET Core MVC and I'm having trouble retrieving a DateTime value from the database into the 'Edit' razor view.
I can use the scaffolded views to create a new Activity Item and this displays correctly in the 'Index' list, and in the 'Details' view, but when I attempt to 'Edit' the entry the DateTime value doesn't pull through from the database.
I've done plenty of reading but the main thing I seem to get in search results is information about JQuery Datepickers.
Any advice on where to look, how to resolve would be very much appreciated.
Here is my model:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MISDataRepo.Models
{
[Table("Activity",Schema = "coir")]
public partial class ActivityItem
{
public ActivityItem()
{
ActivityIdentifier = new HashSet<ActivityIdentifier>();
}
[Key]
public int ActivityItemId { get; set; }
[Required(ErrorMessage = "A valid Activity Name is required.")]
[Display(Name = "Activity Name")]
[StringLength(100)]
public string ActivityName { get; set; }
[Required]
[Display(Name = "Activity Type")]
public int ActivityTypeId { get; set; }
[Required]
[Display(Name = "Date Activity Created")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime DateCreated { get; set; }
[Display(Name = "Date Activity Modified")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime? DatetModified { get; set; }
[Required]
[Display(Name = "Created By (Employee ID)")]
[RegularExpression("^[1-9][0-9]{6}$", ErrorMessage = "A valid Employee ID is required!")]
public int? CreatedBy { get; set; }
[Display(Name = "Project Co-Ordinator (Employee ID)")]
[RegularExpression("^[1-9][0-9]{6}$", ErrorMessage = "A valid Employee ID is required!")]
public int? PC { get; set; }
[DefaultValue(true)]
public bool Live { get; set; }
public virtual ActivityType ActivityType { get; set; }
public virtual ICollection<ActivityIdentifier> ActivityIdentifier { get; set; }
}
}
Here is the view:
#model MISDataRepo.Models.ActivityItem
#{
ViewData["Title"] = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Edit</h1>
<h4>ActivityItem</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="ActivityItemId" />
<div class="form-group">
<label asp-for="ActivityName" class="control-label"></label>
<input asp-for="ActivityName" class="form-control" />
<span asp-validation-for="ActivityName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ActivityTypeId" class="control-label"></label>
<select asp-for="ActivityTypeId" class="form-control" asp-items="ViewBag.ActivityTypeId"></select>
<span asp-validation-for="ActivityTypeId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DateCreated" class="control-label"></label>
<input asp-for="#Html.DisplayFor(a => a.DateCreated)" class="form-control" />
<span asp-validation-for="DateCreated" class="text-danger"></span>
#*<input type="hidden" asp-for="DateCreated" type="date" placeholder="Enter Date Created" value="#Model.DateCreated" />*#
</div>
<div class="form-group">
<label asp-for="DatetModified" class="control-label"></label>
<input asp-for="#Html.DisplayFor(a => a.DatetModified)" class="form-control" />
<span asp-validation-for="DatetModified" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CreatedBy" class="control-label"></label>
<input asp-for="CreatedBy" class="form-control" />
<span asp-validation-for="CreatedBy" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PC" class="control-label"></label>
<input asp-for="PC" class="form-control" />
<span asp-validation-for="PC" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="Live" /> #Html.DisplayNameFor(model => model.Live)
</label>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Here are the 'Edit' methods of the controller
// GET: ActivityItems/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var activityItem = await _context.ActivityItem.FindAsync(id);
if (activityItem == null)
{
return NotFound();
}
ViewData["ActivityTypeId"] = new SelectList(_context.ActivityType, "ActivityTypeId", "ActivityTypeName", activityItem.ActivityTypeId);
return View(activityItem);
}
// POST: ActivityItems/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("ActivityItemId,ActivityName,ActivityTypeId,DateCreated,DatetModified,CreatedBy,PC,Live")] ActivityItem activityItem)
public async Task<IActionResult> Edit(int id, [Bind("ActivityItemId,ActivityName,ActivityTypeId,DatetModified,CreatedBy,PC,Live")] ActivityItem activityItem)
{
if (id != activityItem.ActivityItemId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(activityItem);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ActivityItemExists(activityItem.ActivityItemId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["ActivityTypeId"] = new SelectList(_context.ActivityType, "ActivityTypeId", "ActivityTypeName", activityItem.ActivityTypeId);
return View(activityItem);
}
But when I attempt to 'Edit' the entry the DateTime value doesn't pull
through from the database.
Yes, the issue you are having with the your View is pretty obvious due to your HTML Helper atrribute that is #Html.DisplayFor and the Property you have defined within your Model ActivityItem. You are probably getting following issue.
Problem:
How To Resolve:
Either you could use ViewModel or you can redefine your property public DateTime DateCreated { get; set; } by get rid of your annotations. However, I would prefer to use ViewModel. On the other hands, use the property like asp-for="DateCreated" within your edit view and get rid of your additional HTML helper class #Html.DisplayFor. Follow the below steps.
View Model:
public class ActivityItemViewModel
{
public int ActivityItemId { get; set; }
public string ActivityName { get; set; }
public DateTime DateCreated { get; set; }
public DateTime? DatetModified { get; set; }
}
Note: While loading your Edit view you certainly doesn't require annotations so you can ommit that.
View :
In view you are using additional HTML helper class #Html.DisplayFor which is not required in this scenario. You could try as following:
#model DotNet6MVCWebApp.Models.ActivityItemViewModel
#{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>ActivityItem</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="ActivityItemId" />
<div class="form-group">
<label asp-for="ActivityName" class="control-label"></label>
<input asp-for="ActivityName" class="form-control" />
<span asp-validation-for="ActivityName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DateCreated" class="control-label"></label>
<input asp-for="DateCreated" class="form-control" />
<span asp-validation-for="DateCreated" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DatetModified" class="control-label"></label>
<input asp-for="DateCreated" class="form-control" />
<span asp-validation-for="DatetModified" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="ActivityList">Back to List</a>
</div>
Output:

Failed validation from email input is erasing contents of a different text area ASP.NET

A modal I am working on has some very strange behavior when testing. When the "Email" field fails validation, it clears the "Comment" text area, but leaves all other inputs alone and does not clear them.
Below is the modal page:
#model Project_Name.ViewModels.ProspectViewModel
<!-- Modal -->
<div class="modal fade" id="add-prospect" tabindex="-1" role="dialog" aria-labelledby="addProspectLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form asp-action="Prospect">
<input name="IsValid" type="hidden" value="#ViewData.ModelState.IsValid.ToString()" />
<div class="modal-header">
<h5 class="modal-title" id="addContactLabel">Add Prospect</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label asp-for="firstName"></label>
<input asp-for="firstName" class="form-control" />
<span asp-validation-for="firstName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="lastName"></label>
<input asp-for="lastName" class="form-control" />
<span asp-validation-for="lastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="companyName"></label>
<input asp-for="companyName" class="form-control" />
<span asp-validation-for="companyName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="email"></label>
<input type="email" asp-for="email" class="form-control" />
<span asp-validation-for="email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="cellPhone"></label>
<input type="tel" asp-for="cellPhone" class="form-control" />
<span asp-validation-for="cellPhone" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="comment"></label>
<textarea asp-for="comment" class="form-control" />
<span asp-validation-for="comment" class="text-danger"></span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-default" data-save="modal">Save</button>
</div>
</form>
</div>
</div>
</div>
Here is the model it uses, if that helps:
public class ProspectViewModel
{
public ProspectViewModel()
{
}
public Guid id { get; set; }
public string userId { get; set; }
[Display(Name = "Company Name")]
public string companyName { get; set; }
[Required(ErrorMessage = "First Name is Required")]
[Display(Name ="First Name")]
public string firstName { get; set; }
[Required(ErrorMessage = "Last Name is Required")]
[Display(Name = "Last Name")]
public string lastName { get; set; }
[EmailAddress]
[Display(Name = "Email")]
public string email { get; set; }
[Phone]
[Display(Name = "Cell Phone")]
public string cellPhone { get; set; }
[Display(Name = "Note")]
public string comment { get; set; }
[Display(Name = "Connect Meeting")]
public DateTime? meetingDate { get; set; }
public DateTime createdDate { get; set; }
public string createdBy { get; set; }
public bool isActive { get; set; }
}
Ive cant seem to find any other info on this issue. Thank you in advance.
EDIT: Here is the controller code that opens and posts the modal:
public IActionResult Prospect()
{
var model = new ProspectViewModel();
return PartialView("_AddProspect", model);
}
[HttpPost]
public IActionResult Prospect(ProspectViewModel model)
{
if(model.email == null && model.cellPhone == null)
{
ModelState.AddModelError("email", "Email or Cell Phone is required!");
}
if (ModelState.IsValid)
{
var userId = _userManager.GetUserId(User);
var user = User.Identity.Name;
var prospect = _mapper.Map<Prospect>(model);
prospect.createdDate = DateTime.Now;
prospect.createdBy = user;
prospect.modifiedDate = DateTime.Now;
prospect.modifiedBy = user;
prospect.userId = userId;
prospect.isActive = true;
_unitOfWork.Prospects.Add(prospect);
_unitOfWork.Complete();
TempData["SuccessMessage"] = "Prospect successfully added!";
}
return PartialView("_AddProspect", model);
}
So I'm still unsure WHY it did this, but it appears that since the "comment" field was a text-area element and not an input, and every failed validation of the other input fields would clear the text-area but not the other inputs. When I changed the element to be an , it stopped clearing on other inputs' failed validation.

Why isn't my form validator validating my form?

So I'm trying to create a basic register page where the user needs to fill out all the fields in order to proceed. But the issue I'm facing is that when I click "Create" to finish the process, it just refreshes the page and there are no errors shown, even if I don't fill out any of the fields.
This is the Controller
public IActionResult Register()
{
return View();
}
This is the form
<form>
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Username" class="control-label"></label>
<input asp-for="Username" class="form-control" />
<span asp-validation-for="Username" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ConfirmPassword" class="control-label"></label>
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="Agree" /> #Html.DisplayNameFor(model => model.Agree)
</label>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
And obviously the model
public class RegisterAccountModel
{
[Required(ErrorMessage = "This field is required.")]
[StringLength(60, MinimumLength = 3)]
[DataType(DataType.Text)]
public string Username { get; set; }
[Required(ErrorMessage = "This field is required.")]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required(ErrorMessage = "This field is required.")]
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "The Password and Confirm password must match.")]
public string ConfirmPassword { get; set; }
[Required(ErrorMessage = "This field is required.")]
//[DataType(DataType.Password)]
public bool Agree { get; set; }
}
Why is the page just refreshing without showing any errors when I click the "Create" button?
You need to use the model state valid to start the valuation
public IActionResult Register()
{
if (ModelState.IsValid) { //checking model state
// send to the original action
return RedirectToAction("Index");
}
return View();
}

Form not submitting in asp.net core mvc 2.2.1

I am facing a problem submitting a form in ASP.NET-core 2.2.1 MVC. I realized that the form does not submit when I click on the submit button. I have confirmed that the validation token is there and I have indicated the action path.
I generated the form from a ViewModel. Here is the view Model below
public class SignUpViewModel
{
[Required]
public string Surname { get; set; }
[Required,Display(Name ="Other Names")]
public string Othernames { get; set; }
[EmailAddress,Required,Display(Name ="Email Address")]
public string EmailAddress { get; set; }
[Display(Name ="Phone Number"),DataType(DataType.PhoneNumber),MinLength(11,ErrorMessage ="Phone number should be a valid GSM Mobile number"),Required]
public string PhoneNumber { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "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 Gender Gender { get; set; }
[Display(Name ="State of Residence"),Required]
public int? ResidenceState { get; set; }
[Display(Name ="Local Government of Residence")]
public int? ResidenceLga { get; set; }
[Display(Name ="Date of Birth"),DataType(DataType.Date)]
public DateTime? DateOfBirth { get; set; }
}
The form is here
<form asp-action="signup" method="POST">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Surname" class="control-label"></label>
<input asp-for="Surname" class="form-control" />
<span asp-validation-for="Surname" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Othernames" class="control-label"></label>
<input asp-for="Othernames" class="form-control" />
<span asp-validation-for="Othernames" class="text-danger">
</span>
</div>
<div class="form-group">
<label asp-for="EmailAddress" class="control-label"></label>
<input asp-for="EmailAddress" class="form-control" />
<span asp-validation-for="EmailAddress" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ConfirmPassword" class="control-label"></label>
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-danger">
</span>
</div>
<div class="form-group">
<label asp-for="Gender" class="control-label"></label>
<select asp-for="Gender" class="form-control" asp-
items="#Html.GetEnumSelectList<Gender>()">
<option selected="selected" value="">--Select--</option>
</select>
<span asp-validation-for="Gender" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ResidenceState" class="control-label"></label>
<select asp-for="ResidenceState" class="form-control" asp-
items="ViewBag.StateId">
<option value="">-Select-</option>
</select>
<span asp-validation-for="ResidenceState" class="text-danger">
</span>
</div>
<div class="form-group">
<label asp-for="ResidenceLga" class="control-label"></label>
<select asp-for="ResidenceLga" class="form-control"><option
value="">-Select State First-</option></select>
<span asp-validation-for="ResidenceLga" class="text-danger">
</span>
</div>
<div class="form-group">
<label asp-for="DateOfBirth" class="control-label"></label>
<input asp-for="DateOfBirth" class="form-control" />
<span asp-validation-for="DateOfBirth" class="text-danger">
</span>
</div>
<div class="form-group">
<input type="submit" value="Register" class="btn btn-primary" />
</div>
</form>
The Controller is as follows:
public IActionResult Signup()
{
ViewData["StateId"] = new SelectList(_context.States, "Id", "Name");
return View();
}
[HttpPost]
//[ValidateAntiForgeryToken]
public async Task<ActionResult> Signup(SignUpViewModel model)
{
if (EmailExists(model.EmailAddress))
{
ModelState.AddModelError("", "This email address is already registered with us.");
}
if (ModelState.IsValid)
{
try
{
Enrollee enrollee = new Enrollee {
Surname=model.Surname,
OtherNames=model.Othernames,
Email=model.EmailAddress,
Gender=model.Gender,
StateId=model.ResidenceState,
LgaId=model.ResidenceLga,
DateOfBirth=model.DateOfBirth
};
var result = await _userManager.CreateAsync(enrollee, model.Password);
if (result.Succeeded)
{
//send password the new staff's email
var body = "<p>Email From {0} ({1})</p><p>Message:</p><p>{2}</p>";
var baseurl = $"{Request.Scheme}://{Request.Host}{Request.PathBase}";
var loginurl = baseurl + "/User/Login";
var msg = "Congratulations! " + model.Othernames + "," + "<br />" + "You have just been registered on the eSchool portal." + "<br />" + "Use this email as your login username and the password you registered with to login to the portal:" + "<br />" + "<br />" + "Click <strong><a href='" + loginurl + "'>here</a></strong> to login" + "\r" + "\r";
var message = string.Format(body, "eSchool Portal", "registration#eschoolnigeria.com", msg);
await _emailSender.SendEmailAsync(model.EmailAddress, "Registration on eSchool portal", message);
return RedirectToAction(nameof(Signup));
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty,
error.Description);
}
}
catch (Exception e)
{
ModelState.AddModelError("",e.Message.ToString());
}
}
else
{
ModelState.AddModelError(string.Empty, "Something went wrong
with the process. Please retry");
}
return RedirectToAction(nameof(Signup));
}
I will appreciate any guide to the error making the form not to submit.
Thank you
In your [HttpPost] Signup(...) Action you are always returning RedirectToAction(nameof(Signup)) which will cause you to end up back on the same page with a blank form

How do I pass the values from my form into an email body using MVC 5 C#

Ok so, I have a contact form on my website. I have the ability to send the email with the labels, but I can't seem to get the values to send. So, essentially my Email will look like
First Name:
Last Name:
Company:
Comments:
I just want to know what I am doing wrong.
Controller
[HttpGet]
public IActionResult Contact()
{
ViewData["Message"] = "Contact Us TODAY!";
return View();
}
[HttpPost]
public IActionResult SendEmail()
{
var NewContact = new Forms();
string body = "First Name: " + NewContact.FirstName + "\n"
+ "Last Name:" + NewContact.LastName + "\n"
+ "Company:" + NewContact.Company + "\n\n"
+ "Comments:" + NewContact.Comments;
MailMessage mailBody = new MailMessage("Something#example.com", "Somethingelse#example.com");
mailBody.Subject = "Contact Form";
mailBody.Body = body;
SmtpClient smtpClient = new SmtpClient("smtp.aol.com", 587);
smtpClient.Credentials = new NetworkCredential()
{
UserName = UserNameHidden,
Password = PasswordHidden
};
smtpClient.EnableSsl = true;
smtpClient.Send(mailBody);
return Redirect("Contact");
}
View Page
<form asp-controller="Home" asp-action="SendEmail" name="ContactUs" method="post" class="bs-example-form">
<div class="row">
<div class="row">
<div class="text-danger" asp-validation-summary="ValidationSummary.All">
<p></p>
</div>
<div class="col-sm-6">
<div class="form-group">
<label asp-for="FirstName">First Name:</label>
<input class="form-control" asp-for="FirstName" placeholder="First Name*" type="text" required />
<span asp-validation-for="FirstName" class="text-danger"></span>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label asp-for="LastName">Last Name:</label>
<input class="form-control" asp-for="LastName" placeholder="Last Name*" type="text" required />
<span asp-validation-for="LastName" class="text-danger"></span>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label asp-for="PhoneNumber">Phone:</label>
<input class="form-control" asp-for="PhoneNumber" type="tel" asp-format="000-000-0000" onloosefocus="format" placeholder="Phone Number*" required />
<span asp-validation-for="PhoneNumber" class="text-danger"></span>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label asp-for="Email">Email:</label>
<input class="form-control" asp-for="Email" type="email" placeholder="Email*" title="example#meems.org" required />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
</div>
<span class="formspacer"></span><hr />
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label asp-for="Company">Company:</label>
<input class="form-control" asp-for="Company" placeholder="Company*" title="If you do not represent a company, please type 'NONE'." required />
<span asp-validation-for="Company" class="text-danger"></span>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label asp-for="StreetAddress">Street Address:</label>
<input class="form-control" asp-for="StreetAddress" placeholder="Street Address*" required />
<span asp-validation-for="StreetAddress" class="text-danger"></span>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label asp-for="City">City:</label>
<input class="form-control" asp-for="City" placeholder="City*" required />
<span asp-validation-for="City" class="text-danger"></span>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label asp-for="State">State:</label>
<input class="form-control" asp-for="State" placeholder="State*" required />
<span asp-validation-for="State" class="text-danger"></span>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label asp-for="ZipCode">Zip:</label>
<input class="form-control" asp-for="ZipCode" placeholder="Zip Code*" required />
<span asp-validation-for="ZipCode" class="text-danger"></span>
</div>
</div>
<div class="col-sm-12 bg-grey">
<div class="form-group">
<label asp-for="Comments">Comments:</label>
<input class="form-control" asp-for="Comments" placeholder="Comments" />
</div>
</div>
</div>
<div class="clearfix"></div>
<div class="row">
<div class="col-sm-12">
<div class="buttonWrapper text-center">
<button class="btn btn-primary" type="reset" role="button">Reset</button>
<button class="btn btn-danger" type="submit" role="button" title="Coming Soon Please Just Email Us With This Information">Send</button>
Model
public class Forms
{
//Company Contact Information Customer
public string Company { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string Email { get; set; }
[Required]
public long PhoneNumber { get; set; }
public string Comments { get; set; }
//Company Address Customer
[Required]
public string StreetAddress { get; set; }
[Required]
public string City { get; set; }
[Required]
public string State { get; set; }
[Required]
public string ZipCode { get; set; }
}
Take a look at this.
[HttpPost]
public IActionResult SendEmail()
{
var NewContact = new Forms();
// Existing code
}
You are creating a totally new object of Forms class. This new object properties will have the default values, not the values you have in the form you posted.
What you can do is, Add a parameter to the SendEmail action method of type Forms. When the form is submitted, the DefaultModelBinder will map the form fields to the parameter as the property names matches with the form field names.
[HttpPost]
public IActionResult SendEmail(Forms NewContact)
{
// Existing code which reads from NewContact object property values
}
You are declaring a new Forms object rather than passing it in a parameter in you post method. So the fields are all initialized to default values.
As Nick said, you need to pass a model as an argument to your controller method.
You also need to check model's validation state before using its values, and (typically) return the same view if model is invalid, so validation errors are shown to user.
So your method might be something like:
[HttpPost]
public IActionResult SendEmail(Forms NewContact)
{
if (ModelState.IsValid)
{
// model is valid, you can send email now
string body = "First Name: " + NewContact.FirstName + "\n"
+ "Last Name:" + NewContact.LastName + "\n"
+ "Company:" + NewContact.Company + "\n\n"
+ "Comments:" + NewContact.Comments;
MailMessage mailBody = new MailMessage("Something#example.com", "Somethingelse#example.com");
mailBody.Subject = "Contact Form";
mailBody.Body = body;
SmtpClient smtpClient = new SmtpClient("smtp.aol.com", 587);
smtpClient.Credentials = new NetworkCredential()
{
UserName = UserNameHidden,
Password = PasswordHidden
};
smtpClient.EnableSsl = true;
smtpClient.Send(mailBody);
return Redirect("Contact");
}
else
{
// model contains validation errors
// return the same view so form is populated with existing values,
// and validation errors are shown
//
// You are responsible for populating model values in view page
// it will be done automatically if you're using tag helpers like #Html.EditorFor()
return View("Contact", model);
}
}
Also sending mail might take some time, so you'd better make your controller method asynchronous.

Categories

Resources