I can't understand why the data is not transferred to the database
There is a controller
public class PeopleController : Controller
{
private readonly string ConnectionString = "Host=localhost;Port=5432;Database=CrudDb;Username=postgres;Password=12345;Maximum Pool Size=100";
[HttpGet]
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create(People people)
{
if (ModelState.IsValid)
{
IDbConnection con;
string insertQuery = "INSERT INTO people(name, phone) VALUES(#Name, #Phone)";
con = new NpgsqlConnection(ConnectionString);
con.Open();
con.Execute(insertQuery, people);
con.Close();
return RedirectToAction(nameof(Index));
}
return View(people);
}
}
There is a model for her
public class People
{
public int Id { get; set; }
public string Name { get; set; }
public int Phone { get; set; }
}
And there is a page
<form asp-action="Contacts">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="col-form-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="Phone" class="col-form-label">Телефон </label>
<input asp-for="Phone" class="form-control" />
<span asp-validation-for="Phone" class="text-danger"></span>
</div>
<div class="form-group p-4">
<input type="submit" value="Создать" class="btn btn-outline-success btn-sm" />
</div>
</form>
It does not issue any errors, I enter data on the page, but this data is not transmitted to the database. From libraries, Dapper and Npgsql are connected
Related
I've got number of places where I need to use an address in my app so I tried to make this DRY and create an address partial view like this:
#model AddressEditViewModel
<div class="mb-3">
<label asp-for="Address1" class="form-label"></label>
<input asp-for="Address1" class="form-control" />
<span asp-validation-for="Address1" class="text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="Address2" class="form-label"></label>
<input asp-for="Address2" class="form-control" />
<span asp-validation-for="Address2" class="text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="City" class="form-label"></label>
<input asp-for="City" class="form-control" />
<span asp-validation-for="City" class="text-danger"></span>
</div>
<div class="row mb-3">
<div class="col-md">
<label asp-for="USStateID" class="form-label"></label>
<select asp-items="#Model.USStates" asp-for="USStateID" class="form-select"></select>
<span asp-validation-for="USStateID" class="text-danger"></span>
</div>
<div class="col-md">
<label asp-for="Zip" class="form-label"></label>
<input asp-for="Zip" class="form-control" />
<span asp-validation-for="Zip" class="text-danger"></span>
</div>
</div>
But I had no luck when I put it into another page with the partial tag helper:
<partial name="_Address" model="Model.Address" />
Now I understand why this technique doesn't work - that partial views are just for making HTML and don't get processed by the model binder on the way back.
But I would prefer not to copy and paste forms all over my site. Is there any better way to reuse commonly used form bits like this?
You can use this method.
#await Html.PartialAsync("_PartialName", customViewData)
You can find more details in here.
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/partial?view=aspnetcore-7.0#access-data-from-partial-views
You need to make sure the type of Model.Address is AddressEditViewModel.And make sure the partial view is in the right folder so that you can call it.
Model:
public class TestModel {
public AddressEditViewModel Address { get; set; }
}
public class AddressEditViewModel {
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public int USStateID { get; set; }
public List<SelectListItem> USStates { get; set; }
public string Zip { get; set; }
}
Action:
public IActionResult B()
{
return View(new TestModel {Address=new AddressEditViewModel { Address1="d1",Address2="d2", City="C", USStates=new List<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem> { }, Zip="111"} });
}
_Address.cshtml path:
Views/Shared/_Address.cshtml
B.cshtml:
#model TestModel
<partial name="_Address" model="Model.Address" />
result:
Im just starting ASP.NET 5 Core MVC. I used identity for register. When I submit the register form, Model.isValid returns false in the post of razor page. The only thing that gets posted is the dropdown Item, all others are null. If I remove the role dropdown from the register and then submit it works fine.(Input.Name is the role)
namespace SoftcodeWebGem.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class RegisterModel : PageModel
{
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly UserManager<ApplicationUser> _userManager;
private readonly ILogger<RegisterModel> _logger;
private readonly IEmailSender _emailSender;
private readonly RoleManager<IdentityRole> _roleManager;
public RegisterModel(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
ILogger<RegisterModel> logger,
IEmailSender emailSender,
RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
_emailSender = emailSender;
_roleManager = roleManager;
}
[BindProperty]
public InputModel Input { get; set; }
public string ReturnUrl { get; set; }
public IList<AuthenticationScheme> ExternalLogins { get; set; }
public class InputModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { 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 string Name { get; set; }
}
//public void OnGet(string returnUrl = null)
//{
// ViewData["roles"] = _roleManager.Roles.ToList();
// ReturnUrl = returnUrl;
//}
public async Task OnGetAsync(string returnUrl = null)
{
ViewData["roles"] = _roleManager.Roles.ToList();
ReturnUrl = returnUrl;
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
var role = _roleManager.FindByIdAsync(Input.Name).Result;
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = Input.Email, Email = Input.Email, FirstName = Input.FirstName, LastName = Input.LastName };
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
await _userManager.AddToRoleAsync(user, role.Name);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
ViewData["roles"] = _roleManager.Roles.ToList();
}
// If we got this far, something failed, redisplay form
return Page();
}
}
}
ScreenShot of The Debug
The below code is the Select element
#page
#model RegisterModel
#{
ViewData["Title"] = "Register";
var roles = (List<IdentityRole>)ViewData["roles"];
}
<div class="container">
<div style="padding-top:80px;"></div>
<div class="container pt-5 pb-3" style="background-color: white;
width:500px; height:auto; border-radius:10px;">
<div class="text-center">
<h3>Softcode Gem Solution</h3>
<h6><img src="~/images/icons/add_user_male_32px.png" alt="Register" />Register with your Credentials</h6>
</div>
<form asp-route-returnUrl="#Model.ReturnUrl" method="post">
#Html.AntiForgeryToken()
<div class="form-floating mb-3 ">
<input asp-for="Input.FirstName" type="text" class="form-control" id="firstname" name="firstname" placeholder="First Name" style="border-radius: 5px; ">
<label asp-for="Input.FirstName"><img src="~/images/icons/name_24px.png" />First Name</label>
<span asp-validation-for="Input.FirstName" class="text-danger"></span>
</div>
<div class="form-floating mb-3">
<input asp-for="Input.LastName" type="text" class="form-control" id="lastname" name="lastname" placeholder="Last Name" style="border-radius: 5px; ">
<label asp-for="Input.LastName"><img src="~/images/icons/name_24px.png" />Last Name</label>
<span asp-validation-for="Input.LastName" class="text-danger"></span>
</div>
<div class="form-floating mb-3">
<input asp-for="Input.Email" type="email" class="form-control" id="email" name="email" placeholder="Email" style="border-radius: 5px; ">
<label asp-for="Input.Email"><img src="~/images/icons/email_24px.png" />Email address</label>
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-floating mb-3 pb-2">
<input asp-for="Input.Password" type="password" class="form-control" id="password" name="password" placeholder="Password" style="border-radius: 5px;">
<label asp-for="Input.Password"><img src="~/images/icons/password_24px.png" />Password</label>
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-floating mb-3 pb-2">
<input asp-for="Input.ConfirmPassword" type="password" class="form-control" id="confirmpassword" name="confirmpassword" placeholder="Confirm Password" style="border-radius: 5px;">
<label asp-for="Input.ConfirmPassword"><img src="~/images/icons/password_24px.png" />Confirm Password</label>
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<div class="form-control mb-3 pb-2">
<label asp-for="Input.Name"></label>
<select asp-for="Input.Name" class="form-control" asp-items='new SelectList((List<IdentityRole>)ViewData["roles"], "Id", "Name")'></select>
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
<button class="w-100 btn btn-lg btn-primary " type="submit">Register</button>
<a asp-page="./Login" asp-route-returnUrl="#Model.ReturnUrl" style="text-decoration:none;"><p class="mt-3 mb-2 text-muted ">Already Registered? Login</p></a>
</form>
</div>
#section Scripts {
<partial name="_ValidationScriptsPartial" />
}
There are many questions similar to this but none of them use identity or that what I found. Please help
In your code it looks like there is a conflict in Name as in your Register.chtml
First change the public string Name { get; set; } code in the RegisterModel to
[Display(Name = "User Role")]
public string UserRole { get; set; }
Then look at this part of your code input.Name and the Name in the SelectList:
<div class="form-control mb-3 pb-2">
<label asp-for="Input.Name"></label>
<select asp-for="Input.Name" class="form-control" asp-items='new SelectList((List<IdentityRole>)ViewData["roles"], "Id", "Name")'></select>
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
Just try changing to this:
<div class="form-control mb-3 pb-2">
<label asp-for="Input.UserRole"></label>
<select asp-for="Input.UserRole" class="form-control" asp-items='new SelectList((List<IdentityRole>)ViewData["roles"], "Id", "Name")'></select>
<span asp-validation-for="Input.UserRole" class="text-danger"></span>
</div>
`
fix action OnGetAsync, add Roles
....
ViewBag.Roles = _roleManager.Roles.Select (i=> new SelectListItem {
Value= i.Id.ToString(),
Text= i.Name
}).ToList();
....
and view
<select asp-for="Input.Name" class="form-control" asp-items="#ViewBag.Roles"></select>
And I can't see your Input but something tells me that instead of Input.Name you have to use Input.Id or create it.
How can one have a null object, instead of an empty objet (all properties to null) ? More specifically when the given object's name is not in the form.
Here is my example. I'm posting a simple form to my controller. I have some data bound to p_user, and p_password, but not to p_info. I would have expected it to be null.
Note : All the objects are Entities obtained using a DbFirst Approach with EntityFramework.
Instead, I have the following :
Form :
<form id="accountForm" method="post" action="#Url.Action("CreateAccount")">
<div class="form-group">
<label for="email">EMail</label>
<input id="email" class="form-control" type="email" name="p_user.email" aria-describedby="emailHelp" placeholder="Enter your email address" />
</div>
<div class="form-group">
<label for="username">Username</label>
<input id="username" name="p_user.username" class="form-control " type="text" aria-describedby="usernameHelp" placeholder="Enter your username" />
<small id="usernameHelp" class="form-text text-muted"></small>
</div>
<div class="form-group">
<label for="password">Password</label>
<input id="password" name="p_password" class="form-control" type="password" placeholder="Enter your password">
</div>
<button type="submit" class="btn btn-primary">Créer</button>
</form>
Controller :
public ActionResult CreateAccount(T_User p_user, string p_password, T_UserInfo p_info = null)
T_UserInfo :
public partial class T_UserInfo
{
public int id_user { get; set; }
public string forname { get; set; }
public string lastname { get; set; }
public string avatar_path { get; set; }
public virtual T_User T_User { get; set; }
}
I am trying to make a validation for my report form where the report can only be submited if the email = to "Sample#email.com". My problem is the code works perfectly without the validation but when I include the validation code if (!ModelState.IsValid){return View("Create");} into the my controller the validation works perfectly but when the email is correct it just refreshes the page without submiting it or redirecting it to the submit view
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Submit(Reports report)
{
if (!ModelState.IsValid)
{
return View("Create");
}
_reportRepository.CreateReport(report);
return View();
Validation Code:
public class EmailValidation : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var report = (Reports)validationContext.ObjectInstance;
if (report.Email == "Sample#email.com")
{
return ValidationResult.Success;
}
return new ValidationResult("Invalid email");
}
}
Report:
public class Reports
{
[Key]
public int ReportId { get; set; }
[Required(ErrorMessage = "Please enter email.")]
[Display(Name = "Email :")]
[EmailValidation(ErrorMessage ="enter valid email")]
public string Email { get; set; }
}
Create View:
#model Reports
#using Microsoft.AspNetCore.Identity
#inject UserManager<IdentityUser> UserManager
<body>
<form asp-action="Submit" method="post" role="form">
<div class="container1">
<div class=" form-group row">
<label asp-for="Email" class="col-md-2 control-label"></label>
<div class="col-md-3">
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
<div class="form-group row float-right">
<div class="col-md-offset-2 col-md-5 float-md-left">
<input type="submit" class="btn btn-primary" value="Submit" />
</div>
</div>
I have the code working in a new seperate test project how ever it will not work with my excisting work project. I am trying to upload a file as part of a form, store it in a folder in wwwroot and store the url in a database. I have posted the code below.The program compiles and runs but does not store anything when create button is pressed. any help would be greatly appreciated.
//Model
namespace PostProjectEvaluations.Web.Models
{
public partial class Projects
{
[Key]
public int ProjectId { get; set; }
[Required]
[StringLength(300)]
public string Name { get; set; }
[Required]
[StringLength(50)]
public string Manager { get; set; }
public string FilePath { get; set; }
}
public class ProjectsVM
{
public string Name { get; set; }
public IFormFile File { get; set; }
}
//Controller
namespace PostProjectEvaluations.Web.Controllers
{
public class projectsController : Controller
{
private readonly IApplicationRepository ApplicationRepository;
private readonly PostProjectEvaluationsContext _context;
private IHostingEnvironment mxHostingEnvironment { get; set; }
private object objproject;
public projectsController(IApplicationRepository applicationRepository,
IHostingEnvironment hostingEnvironment, PostProjectEvaluationsContext context)
{
mxHostingEnvironment = hostingEnvironment;
ApplicationRepository = applicationRepository;
_context = context;
}
public IActionResult Index()
{
ViewBag.dataSource = ApplicationRepository.GetAllProjects().ToList();
var projects = ApplicationRepository.GetAllProjects();
return View(projects);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Index(ProjectsVM projectsVM)
{
if (projectsVM.File != null)
{
//upload files to wwwroot
var fileName = Path.GetFileName(projectsVM.File.FileName);
var filePath = Path.Combine(mxHostingEnvironment.WebRootPath, "Uploads", fileName);
using (var fileSteam = new FileStream(filePath, FileMode.Create))
{
await projectsVM.File.CopyToAsync(fileSteam);
}
//your logic to save filePath to database, for example
Projects projects = new Projects();
projects.Name = projectsVM.Name;
projects.FilePath = filePath;
_context.Projects.Add(projects);
_context.SaveChanges();
}
else
{
}
return View("Index");
}
public IActionResult Details(int id)
{
var project = ApplicationRepository.GetProjects(id);
return View(project);
}
[HttpGet]
public IActionResult Create()
{
var project = new Projects();
return View(project);
}
[HttpPost]
public IActionResult Create(Projects projects)
{
ApplicationRepository.Create(projects);
return RedirectToAction("Index");
}
public IActionResult Delete(int id)
{
var project = ApplicationRepository.GetProjects(id);
ApplicationRepository.Delete(project);
return RedirectToAction("Index");
}
[HttpGet]
public IActionResult Edit(int id)
{
var project = ApplicationRepository.GetProjects(id);
//mxApplicationRepository.SaveChangesAsync();
return View(project);
}
[HttpPost]
public IActionResult Edit(Projects projects)
{
ApplicationRepository.Edit(projects);
//mxApplicationRepository.SaveChangesAsync();
return RedirectToAction("Index");
}
}
}
//View
<form enctype="multipart/form-data" asp-controller="Projects" asp-action="Create" method="post" class="form-horizontal">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-body">
<h3 class="form-section">Project Info</h3>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="control-label col-md-3">Project Name</label>
<div class="col-md-9">
<input asp-for="Name" class="form-control" placeholder="Name">
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
</div>
<!--/span-->
<div class="col-md-6">
<div class="form-group">
<label class="control-label col-md-3">Project Manager</label>
<div class="col-md-9">
<input asp-for="Manager" class="form-control" placeholder="Name">
</div>
</div>
</div>
<!--/span-->
</div>
<!--/span-->
</div>
<h3 class="form-section">Project Files</h3>
<!--/row-->
<div class="row">
<div>
<div class="col-md-6">
<div class="col-md-10">
<p>Upload one or more files using this form:</p>
<input type="file" name="files" multiple />
</div>
</div>
</div>
<div>
</div>
</div>
<div class="form-actions right">
<input type="submit" class="btn blue-assembly" name="submitButton" value="Save" />
<a asp-action="Index" class="btn default" onclick="cancelClick()">Cancel</a>
</div>
Include your model in view as in the first line
#ProjectsVM
You have to give the same name as a model
Try this:
<input type="file" id= name="File" multiple />