ASP.NET MVC HttpPost async task not functioning correctly - c#

I am trying to create a form in my actors page. Upon clicking the submit button, fields are validated and it should in theory submit, but it is not. I have tried renaming, creating a new function that intellisense suggests and my only ways of making this form to submit is either manually making the function go to _service.Add(actor); or by not going with the validation, but then if one of the required fields is not met, it throws an error in a different page, which is not ideal. I have no clue how to make this work, because the course, that I am recreating it from is able to do it just fine.
My code - controller:
namespace Cinema_World.Controllers
{
public class ActorsController : Controller
{
private readonly IActorsService _service;
public ActorsController(IActorsService service)
{
_service = service;
}
public async Task<IActionResult> Index()
{
var allActors = await _service.GetAll();
return View(allActors);
}
public async Task<IActionResult> Create()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Create([Bind("FirstName,MiddleName,LastName,BirthYear,BirthPlace")] ActorModel actor)
{
if (!ModelState.IsValid) //when i use break-points, this part gets stepped into
{// also this part
return View(actor); //this part too
} // and this is the final part, then it skips to the end and nothing happens in the browser
_service.Add(actor);
return RedirectToAction(nameof(Index));
}
}
}
My models:
namespace Cinema_World.Models
{
public class ActorModel
{
[Key]
public int ActorID { get; set; }
[Display(Name = "First name")]
[Required(ErrorMessage = "First name is a required field")]
[StringLength(100, MinimumLength = 1, ErrorMessage = "First name can be between 1 and 100 characters long!")]
public string FirstName { get; set; }
[Display(Name = "Middle name")]
[StringLength(100, MinimumLength = 1, ErrorMessage = "Middle name can be between 1 and 100 characters long!")]
public string? MiddleName { get; set; }
[Display(Name = "Last name")]
[Required(ErrorMessage = "Last name is a required field")]
[StringLength(100, MinimumLength = 1, ErrorMessage = "Last name can be between 1 and 100 characters long!")]
public string LastName { get; set; }
[Display(Name = "Year of Birth")]
[Required(ErrorMessage = "Year of birth is a required field")]
[Range(999,9999, ErrorMessage = "Input a year between 999 and 9999")]
public int BirthYear { get; set; }
[Display(Name = "Place of Birth")]
[Required(ErrorMessage = "Place of birth is a required field")]
[StringLength(100, MinimumLength = 1, ErrorMessage = "Name of the place can be between 1 and 100 characters long!")]
public string BirthPlace { get; set; }
public List<Actor_CinematographyModel> Actors_Cinematography { get; set; }
}
}
Code from my service that gets called, when form submit is successful.
namespace Cinema_World.Data.Services
{
public class ActorsService : IActorsService
{
private readonly ApplicationDbContext _context;
public ActorsService(ApplicationDbContext context)
{
_context = context;
}
public void Add(ActorModel Actor)
{
_context.Actors.Add(Actor);
_context.SaveChanges();
}
public void Delete(int ActorID)
{
throw new NotImplementedException();
}
public async Task<IEnumerable<ActorModel>> GetAll()
{
var result = await _context.Actors.ToListAsync();
return result;
}
public ActorModel GetById(int ActorID)
{
throw new NotImplementedException();
}
public ActorModel Update(int ActorID, ActorModel newActor)
{
throw new NotImplementedException();
}
}
}
Interface for this specific service:
namespace Cinema_World.Data.Services
{
public interface IActorsService
{
Task<IEnumerable<ActorModel>> GetAll();
ActorModel GetById(int ActorID);
void Add(ActorModel Actor);
ActorModel Update(int ActorID, ActorModel newActor);
void Delete(int ActorID);
}
}
View markup:
<div class="row text">
<div class="col-md-8 offset-2">
<p>
<h1>Add a new Actor!</h1>
</p>
<div class="row">
<div class="col-md-8 offset-2">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="FirstName" class="control-label"></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="MiddleName" class="control-label"></label>
<input asp-for="MiddleName" class="form-control" />
<span asp-validation-for="MiddleName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="LastName" class="control-label"></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="BirthYear" class="control-label"></label>
<input asp-for="BirthYear" class="form-control" />
<span asp-validation-for="BirthYear" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BirthPlace" class="control-label"></label>
<input asp-for="BirthPlace" class="form-control" />
<span asp-validation-for="BirthPlace" class="text-danger"></span>
</div>
<div class="form-group mt-2">
<input type="submit" value="Create" class="btn btn-outline-success float-end"/>
<a class="btn btn-outline-dark" asp-action="Index">Show all</a>
</div>
</form>
</div>
</div>
</div>
</div>
If anything else is required, please, let me know. I have been stuck hard on this for a while already, and if I am not able to fix this, I cannot progress with my other forms.
Like I said before, I tried replacing the !ModelState.IsValid with ModelState.IsValid and putting the executing code in there, intellisense suggestions and even manually, using break-points and I did manage to get it to work like that, but is not an ideal choice.
My knowledge in ASP.NET MVC is basic, so perhaps I messed up something or missed something.
Just for clarification - the called service works, i am able to post data, but if validation is present in the same method, i am unable to post anything and the button does not do anything.

Turns out, the problem was not in the method, but the model.
public List<Actor_CinematographyModel> Actors_Cinematography { get; set; } was somehow conflicting and not allowing me to post data. after making it possible to be a null value, everything works. not sure, why it did it, maybe i set up my database tables wrong. this thread is no longer in question :)

Related

How to bind dropdownlist in razor pages for modelstate validation?

I have this form built using Razor Pages in C#. The is the code for create.cshtml. It has a dropdown list.
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="MetaDropdown.Id" class="control-label"></label>
<input asp-for="MetaDropdown.Id" class="form-control" />
<span asp-validation-for="MetaDropdown.Id" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MetaDropdown.MetaFieldId" class="control-label"></label>
<select asp-for="MetaDropdown.MetaFieldId" class="form-control" asp-items="ViewBag.MetaFieldId"></select>
</div>
<div class="form-group">
<label asp-for="MetaDropdown.Value" class="control-label"></label>
<input asp-for="MetaDropdown.Value" class="form-control" />
<span asp-validation-for="MetaDropdown.Value" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="MetaDropdown.active" /> #Html.DisplayNameFor(model => model.MetaDropdown.active)
</label>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
This is the code behind.
public class CreateModel : PageModel
{
private readonly DataContext _context;
public CreateModel(DataContext context)
{
_context = context;
}
public IActionResult OnGet()
{
ViewData["MetaFieldId"] = new SelectList(_context.meta_fields, "Id", "FieldName");
return Page();
}
[BindProperty]
public MetaDropdown MetaDropdown { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.meta_dropdowns.Add(MetaDropdown);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
The issue is when I submit the form, its ModelState.IsValid is false. Upon checking, the error is due to MetaField field is missing. I think this is due to the way I bind the dropdownlist.
This is MetaDropdown model
public class MetaDropdown
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public int MetaFieldId { get; set; }
public string? Value { get; set; }
public bool active { get; set; }
public virtual MetaField MetaField { get; set; }
}
You may use .NET 6/.NET 7. From .NET 6 the non-nullable property must be required, otherwise the ModelState will be invalid.
To achieve your requirement, the first way is you can remove <Nullable>enable</Nullable> from your project file(double-click the project name or right-click the project to choose Edit Project File).
The second way, you can add ? to allow nullable:
public class MetaDropdown
{
public int Id { get; set; }
//other properties....
public virtual MetaField? MetaField{ get; set; } //change here...
}
The third way, you can initialize the model like below:
public class MetaDropdown
{
public int Id { get; set; }
//other properties....
public virtual MetaField MetaField{ get; set; } = new MetaField(); //change here...
}

C# ASP.Net Core Model Validation doesn't work

I have a C# ASP.Net Core MVC Web-Application and I want to make two forms, where I can input a Model. My problem is, one of both work and the other one don't, and I don't understand why.
When I'm saying it doesn't work, I mean, that I get a null value in my LogInWordForm method and the one who works gets the value from the input of the form.
(To add [HTTPPOST] in the controller and method="post" in the cshtml I already tried)
First of all my controller for both [GameController.cs -> C#]:
public class GameController : Controller
{
// ToDo: Aus Singleton es machen, dass es auf User session bezogen ist.
private readonly ILogger<HomeController> _logger;
private Wheelchair instance;
public SimpleGameUser sgu;
public static string moneySession = "_money";
public static string questionSession = "_qanda";
// true : false
public IActionResult LogInWord()
{
if (!CheckSession()) return RedirectToAction("Index", "Home");
return View();
}
public IActionResult LogInWordForm(Word word)
{
if (!CheckSession()) return RedirectToAction("Index", "Home");
if (ModelState.IsValid)
{
string solution = this.sgu.wheelchair.word;
solution = solution.Replace("[", string.Empty);
solution = solution.Replace("]", string.Empty);
solution = solution.Replace("_", " ");
if (word.word.Equals(solution))
return View("GameOver", this.sgu);
else
{
ViewBag.Fail = "Word wasn't guessed.";
return View("WheelSpin", this.instance);
}
}
return View("LogInWord", word);
}
public IActionResult QuestionAndAnswer()
{
return CheckSession() ? View() : RedirectToAction("Home", "Index");
}
public IActionResult QAnswered(QandA qanda)
{
if (!CheckSession()) return RedirectToAction("Index", "Home");
if (sgu.money < qanda.risk)
{
ModelState.AddModelError("risk", "You haven't enough money to risk this!");
}
if (ModelState.IsValid)
{
if(qanda.userAnswer.Equals(qanda.variant))
{
this.sgu.money += qanda.risk;
} else
{
this.sgu.money -= qanda.risk;
}
HttpContext.Session.SaveObject<SimpleGameUser>(sgu, HomeController.userNow);
return WheelSpin();
}
return View("QuestionAndAnswer", qanda);
}
private bool CheckSession()
{
this.sgu = HttpContext.Session.GetObject<SimpleGameUser>(sessionName: HomeController.userNow);
this.instance = sgu.wheelchair;
return sgu != default;
}
Model of the first one who's not working [Word.cs -> C#]:
public class Word : IValidatableObject
{
[Required(ErrorMessage = "This field is required!")]
[Display(Name = "Your word to Log In")]
public string word { get; set; }
public string errors { get; set; } = ";";
public Word()
{
}
public Word(string word)
{
this.word = word;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> errors = new List<ValidationResult>();
List<Char> letters = Consonant.consonants;
letters.AddRange(Consonant.vocals);
letters.Add(',');
letters.Add('.');
letters.Add('_');
if (!letters.Any(s => this.word.Contains(s)))
errors.Add(new ValidationResult("There was an illegal character"));
return errors;
}
}
if someone wants to know: the validation should be testing if there are only characters and some allowed letters used, what I couldn't test yet.
View [LongInWord.cshtml]:
#model Word;
#{
}
<div id="layoutAuthentication_content">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Login</h3></div>
<div class="card-body">
<form asp-action="LogInWordForm" asp-controller="Game">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-floating mb-3">
<input asp-for="word" type="text" />
<label asp-for="word"></label>
<span asp-validation-for="word" class="text-danger"></span>
</div>
<br />
<input class="btn btn-primary" type="submit" />
</form>
</div>
</div>
</div>
</div>
</div>
</div>
Now of the one which is working:
Model [QandA.cs -> C#]:
public class QandA
{
public int ID { get; set; }
[BindProperty, Required(ErrorMessage = "This field can't be empty!")]
[Range(0, 1, ErrorMessage = "This wasn't one of the two given answers...")]
public bool userAnswer { get; set; }
public string question { get; set; }
public string answer0 { get; set; }
public string answer1 { get; set; }
public bool variant { get; set; }
[Required(ErrorMessage = "This field can't be empty!")]
[Range(0, int.MaxValue, ErrorMessage = "Please enter valid positiv integer Number above 0")]
[Display(Name = "Select your risk")]
public int risk { get; set; }
public QandA(string question, string answer0, string answer1, bool variant)
{
this.question = question;
this.answer0 = answer0;
this.answer1 = answer1;
this.variant = variant;
}
public QandA()
{
}
public bool correctAnswered()
{
return this.variant == this.userAnswer;
}
}
View [QuestionAndAnswer.cshtml]:
#model QandA;
#{
}
<div id="layoutAuthentication_content">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Login</h3></div>
<div class="card-body">
<form asp-action="QAnswered" asp-controller="Game">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<h3>#Model.question </h3>
<div class="form-group">
<label asp-for="userAnswer">Example select</label>
<div class="form-control">
<input asp-for="userAnswer" type="radio" class="btn-check" name="options-outlined" id="success-outlined" autocomplete="off" value="0" checked>
<label class="btn btn-outline-success form-control" for="success-outlined">#Model.answer0</label>
<input asp-for="userAnswer" type="radio" class="btn-check" name="options-outlined" id="danger-outlined" autocomplete="off" value="1">
<label class="btn btn-outline-danger form-control" for="danger-outlined">#Model.answer1</label>
</div>
</div>
<br />
<div class="form-group">
<label asp-for="risk"></label>
<input type="number" min="0" class="form-control" />
<span asp-validation-for="risk" class="text-danger"></span>
</div>
<input class="btn btn-primary" type="submit" />
</form>
</div>
</div>
</div>
</div>
</div>
</div>
The model binding doesn't know how to bind this. You have a parameter named word and in the type of the parameter you have a property with the same name.
public class GameController : Controller
{
// ...
// here you have a parameter named word, and in the model type you have a property named the same way
// rename the parameter to something elese - for ex. formData
public IActionResult LogInWordForm(Word word)
{
// ...
}
// ...
}

ASP.NET MVC User ID Link with other Tables

I am working on a Data Entry system for storing users financial data. Each user will enter his Revenues and Expenses each in a table.
The tables were designed as follows:
Primary Key: Rev/Exp ID
Foreign Key: Organization ID
This is a sample for my models:
public class Revenue
{
[Key]
public int RevenueId { get; set; }
public int Year { get; set; }
public double Source1 { get; set; } = 0;
public double Source2 { get; set; } = 0;
public double Source3 { get; set; } = 0;
public double Source4 { get; set; } = 0;
// Foreign Key Relationship
public string OrganizationId{ get; set; }
public virtual Organization Organization{ get; set; }
}
public class Organization
{
public virtual ICollection<Revenue> Revenues { get; set; }
public virtual ICollection<Expense> Expenses { get; set; }
}
This is the DBContext:
public class AppDbContext : IdentityDbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
// Create tables in DB
public DbSet<Organization > Organization { get; set; }
public DbSet<Revenue> Revenue { get; set; }
public DbSet<Expense> Expense { get; set; }
}
Here is the Create Action in the Controller:
// GET: Revenue/Create
public IActionResult Create()
{
return View();
}
// POST: Revenue/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("RevenueId,Year,Source1,Source2,...,OrganizationId")] Revenue revenue)
{
if (ModelState.IsValid)
{
_context.Add(revenue);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["OrganizationId"] = new SelectList(_context.OrganizationId, "Id", "Id", revenue.OrganizationId);
return View(revenue);
}
Finally, Create View:
#using Microsoft.AspNetCore.Identity
#inject SignInManager<IdentityUser> SignInManager
#inject UserManager<IdentityUser> UserManager
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Revenue</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Year" class="control-label"></label>
<input asp-for="Year" class="form-control" />
<span asp-validation-for="Year" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Source1" class="control-label"></label>
<input asp-for="Source1" class="form-control" />
<span asp-validation-for="Source1" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Source2" class="control-label"></label>
<input asp-for="Source2" class="form-control" />
<span asp-validation-for="Source2" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Source3" class="control-label"></label>
<input asp-for="Source3" class="form-control" />
<span asp-validation-for="Source3" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Source4" class="control-label"></label>
<input asp-for="Source4" class="form-control" />
<span asp-validation-for="Source4" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="OrganizationId" class="control-label"></label>
<input asp-for="OrganizationId" class="form-control" value="#UserManager.GetUserId(User)"/>
<span asp-validation-for="OrganizationId" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
So, after a lot of search I was able to capture user ID with UserManager and assigning it to a hidden field, then sending it with the form. However, that did not work, the form is not submitting and no error messages are displayed neither.
Is this is a correct way of capturing user ID as a Foreign Key and how to fix the Create Action ?
You didn't really specify anything about your authentication. If you are using typical ASP.Net authentication, you can probably use User.Identity.Name, like this:
if (ModelState.IsValid)
{
revenue.UserId = User.Identity.Name
_context.Add(revenue);
...
As from .NET 6, in order to assign an attribute in a model to be Nullable the ? should be added after the name of the attribute, otherwise it is required.
The problem was that the UserId is passed but the User object is null (which should be because it is just a reference).
So the model should be:
public class Revenue
{
[Key]
public int RevenueId { get; set; }
public int Year { get; set; }
public double Source1 { get; set; } = 0;
public double Source2 { get; set; } = 0;
public double Source3 { get; set; } = 0;
public double Source4 { get; set; } = 0;
// Foreign Key Relationship
public string OrganizationId{ get; set; }
public Organization? Organization{ get; set; }
}
And the view will be as is by passing user ID in a hidden field that we got from UserManager.

ASP.NET Core 5.0 - POST on custom model

I did it according to youtube tutorial, but unfortunately for me it behaves extremely oddly.
Simple scenario: add comment to a post.
public class CommentViewModel
{
public Post Post { get; set; }
public Comment Comment { get; set; }
}
<p>#Model.Post.Title</p>
<p>#Model.Post.Body</p>
<form method="post" asp-action="NewComment">
<input asp-for="Post.Id" hidden />
<div class="border p-3">
#*<div asp-validation-summary="ModelOnly" class="text-danger"></div>*#
<div class="form-group row">
<h2 class="text-info pl-3">Write new comment</h2>
</div>
<div class="form-group row">
<label asp-for="Comment.Body"></label>
<textarea asp-for="Comment.Body" class="form-control"></textarea>
<span asp-validation-for="Comment.Body" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<div class="col-8 offset-2 row">
<div class="col">
<input type="submit" class="btn btn-info w-100" value="Create" />
</div>
<div class="col">
<a asp-action="Index" class="btn btn-success w-100"><i class="fas fa-sign-out-alt"></i> Back</a>
</div>
</div>
</div>
</form>
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult NewComment(CommentViewModel model)
{
if (ModelState.IsValid)
{
_service.AddNewComment(new Guid(), model.Post.Id, model.Comment.Body);
return RedirectToAction("Index");
}
return View();
}
Models:
public class Post
{
[BsonElement("id")]
public Guid Id { get; set; }
[BsonElement("title")]
[Required]
[MaxLength(64)]
public string Title { get; set; }
[BsonElement("post_body")]
[Required]
[Display(Name = "Post")]
[MaxLength(256)]
public string Body { get; set; }
}
public class Comment
{
[BsonElement("id")]
public Guid Id { get; set; }
[BsonElement("post_id")]
public Guid PostId { get; set; }
[BsonElement("comment_body")]
[Required]
[Display(Name = "Comment")]
[MaxLength(128)]
public string Body { get; set; }
}
When fields are not filled red notification appears, as it should. But once fields are filled and user clicks on create, ModelState.IsValid is still false, and for some reason application tries to reload view, but returns exception on <p>#Model.Post.Title</p> NullReferenceException.
It's extremely weird behavior. Adding new post is almost identical except <input asp-for="Post.Id" hidden /> (since there are no relations to anything else), and it works flawlessly. Here things are glitching out.
Removing if (ModelState.IsValid) and return View(); absolutely fixes the issue. Both validation and POST works. But it should work even with it.
Any clues? All laws of logic say it should work. Otherwise I will be forced to keep it the weird way.
I don't see any weird here. It works according to your code. But you can fix a bug:
if (ModelState.IsValid)
{
_service.AddNewComment(new Guid(), model.Post.Id, model.Comment.Body);
return RedirectToAction("Index");
}
return View(model);
in this case you will not have a null reference exeption.
and by the way I am using this code to find what is invalid in a ModelState:
public static string ValidModelState(ModelStateDictionary modelState)
{
var errorMessage = "";
if (!modelState.IsValid)
{
foreach (var item in modelState.Values)
{
foreach (var modelError in item.Errors)
{
errorMessage += "\n" + "Error: " + modelError.ErrorMessage;
}
}
}
return errorMessage;
}
And using this instead of if (ModelState.IsValid):
var errorMessage = ValidModelState(ModelState);
if( !string.IsNullOrEmpty(errorMessage)).... errorMessage;
It says The Post field is required., except that property does not exist.
You have a [Display(Name = "Post")] on the Post.Body property, And I think the model in the view doesn't have value for Post Body, so the validation failed, and the error message for it is The Post field is required. Go and check it.

Role is null at Post request for ASP.NET Core Razor Pages

I have this Razor Pages which show a textbox and a button. Upon clicked, it will create/insert a Role into the table. Problem is when I put a breakpoint at the OnPostAsync method, role parameter is null.
This is my front-end code:
#page
#model CreateModel
#{
ViewData["Title"] = "Create";
}
<h1>Create Role</h1>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-route-returnUrl="#Model.ReturnUrl" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Name"></label>
<input asp-for="Input.Name" class="form-control" />
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
This is my code-behind:
public class CreateModel : PageModel
{
private readonly RoleManager<IdentityRole> _roleManager;
public CreateModel(RoleManager<IdentityRole> roleManager)
{
_roleManager = roleManager;
}
[BindProperty]
public IdentityRole Name { get; set; }
public InputModel Input { get; set; }
public string ReturnUrl { get; set; }
public class InputModel
{
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 3)]
[Display(Name = "Role Name")]
public IdentityRole Name { get; set; }
//public string Name { get; set; }
}
public void OnGet(string returnUrl = null)
{
ReturnUrl = returnUrl;
}
public async Task<IActionResult> OnPostAsync(IdentityRole role) {
await _roleManager.CreateAsync(role);
return Page();
}
}
The problem may come from the returned type of IdentityRole, in the client, your browser doesn't know how to convert a variable type to IdentityRole. Some popular types are: string, int, List<T>...
So, in this case, I suggest to use a string instead.
public InputModel Input { get; set; }
public class InputModel
{
public string Name { get; set; }
}
public async Task<IActionResult> OnPostAsync() {
await _roleManager.CreateAsync(new IdentityRole { Name = Input.Name });
return Page();
}

Categories

Resources