Cannot add new role in MVC5 Microsoft.AspNet.Identity.EntityFramework.IdentityRole? - entity-framework

I add 3 roles using my MVC application before. Now I cant add new role. When I debug I can see new role Id but the Role name is empty. How can I solve this problem?
I have 3 roles at the moment. User, Admin, Sales. Now I want to add Account role and cannot add.
CONTROLLER
// POST: /Roles/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
context.Roles.Add(new Microsoft.AspNet.Identity.EntityFramework.IdentityRole()
{
Name = collection["RoleName"]
});
context.SaveChanges();
ViewBag.ResultMessage = "Role created successfully !";
return RedirectToAction("Index");
}
catch
{
return View();
}
}
CSHTML
#model Microsoft.AspNet.Identity.EntityFramework.IdentityRole
<div class="container body-content">
#{
ViewBag.Title = "Create";
}
<h2>Create Role</h2>
#Html.ActionLink("List Roles", "Index") | #Html.ActionLink("Manage User Role", "ManageUserRoles")
<hr />
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<p>
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
</p>
<br />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</div>
}
</div>

You should only use viewModels in your view, but as you are using your view and object now, you should adjust your controller the following to use mvc roleManager (much easier):
// POST: /Roles/Create
[HttpPost]
public ActionResult Create(IdentityRole role)
{
try
{
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
roleManager.Create(role)
context.SaveChanges();
ViewBag.ResultMessage = "Role created successfully !";
return RedirectToAction("Index");
}
catch
{
return View();
}
}

Related

How can I bind form fields to a nested model on post?

I am coding a solution where the user will submit a form, posting the values back to my ASP.NET MVC controller. My model is complex and the form fields are contained in a nested object (I'm using CQRS via MediatR). When I submit the form, the values come across as null. How can I get the complex model to recognize the form fields?
Here is my code:
Controller:
[HttpPost]
[Route("edit")]
public async Task<IActionResult> Edit(UpdateApplicationCommand command)
{
await _mediator.Send(command)
.ConfigureAwait(false);
return RedirectToAction("Index");
}
Models:
public class UpdateApplicationCommand : IRequest<Unit>
{
public ApplicationEditGeneralViewModel ApplicationEditGeneralViewModel { get; set; } = null!;
}
public class ApplicationEditGeneralViewModel
{
[Required]
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
}
View:
#model ApplicationEditGeneralViewModel
<form method="post" asp-action="Edit" asp-controller="Applications">
<div class="form-floating mb-3">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control", placeholder = "Application Name"})
<label for="Name">Application Name</label>
</div>
<div class="form-floating mb-3">
#Html.TextBoxFor(m => m.Description, new { #class = "form-control", placeholder = "Application Description"})
<label for="Description">Application Description</label>
</div>
<div class="d-flex flex-row-reverse bd-highlight">
<input type="submit" value="Submit" class="btn btn-primary mt-2" />
</div>
</form>
I've tried to reduce the complex model to its fields, by placing the contents of the ApplicationEditGeneralViewModel directly into the UpdateApplicationCommand class. This worked, but I'd really like to keep the nested structure so that I can reuse the ApplicationEditGeneralViewModel object.
I saw this solution here:
How to bind nested model in partial view
But I'd rather avoid adding the name as a route object (if possible) for every form field. Is there another, more simple way that I can do this?
The first way, you can custom model binding like below:
public class CustomModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
var model = new UpdateApplicationCommand()
{
ApplicationEditGeneralViewModel = new ApplicationEditGeneralViewModel()
{
Description = bindingContext.ValueProvider.GetValue("Description").ToString(),
Name = bindingContext.ValueProvider.GetValue("Name").ToString()
}
};
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
Apply the custom model binding like below:
[HttpPost]
public async Task<IActionResult> Edit([ModelBinder(typeof(CustomModelBinder))]UpdateApplicationCommand model)
{
//.....
}
The second way, just change your razor view like below:
#model UpdateApplicationCommand
<form method="post">
<div class="form-floating mb-3">
#Html.TextBoxFor(m => m.ApplicationEditGeneralViewModel.Name, new { #class = "form-control", placeholder = "Application Name"})
<label for="Name">Application Name</label>
</div>
<div class="form-floating mb-3">
#Html.TextBoxFor(m => m.ApplicationEditGeneralViewModel.Description, new { #class = "form-control", placeholder = "Application Description"})
<label for="Description">Application Description</label>
</div>
<div class="d-flex flex-row-reverse bd-highlight">
<input type="submit" value="Submit" class="btn btn-primary mt-2" />
</div>
</form>

Bind Gender with Radio button in Create and Edit in MVC

I want to show Gender Male Radio Button and Female Radio button on create and on Edit the selected radio button if male then male should be selected if Female then female should be checked.
Model
[Table("tblUserData")]
public class test
{
[Key]
public int Id { get; set; }
public string FullName { get; set; }
public Nullable<bool> Gender { get; set; }
}
Create View
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>test</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.FullName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FullName)
#Html.ValidationMessageFor(model => model.FullName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Gender, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Gender)
#Html.ValidationMessageFor(model => model.Gender)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
How do I replace the
#Html.EditorFor(model => model.Gender)
With
#Html.RadioButtonFor(model=>model.Gender)
It asks for one more parameter where do I get it from as its a Bit in sql if its 0 then Gender is Male if 1 then Female.
Same I want to do it for edit so that user can see the Gender and update it through radio buttons.
Assuming your razor view is strongly typed to your class,test
#model test
#using (Html.BeginForm())
{
#Html.RadioButtonFor(model => model.Gender, true)
<span>Male</span>
#Html.RadioButtonFor(model => model.Gender, false)
<span>FeMale</span>
<input type="submit" />
}
For your edit view, the same code will work as long as you are sending a valid object of test to your view. Based on the value on the Gender property, it will select the corresponding radio button.
public ActionResult Edit(int id)
{
var vm = yourSbContext.tests.FirstOrDefault(s=>s.Id==id);
if(vm!=null)
{
return View(vm);
}
// to do : Return a Not found/404 response/view
}

Post complex model to controller MVC using Facebook application template C#

I have following model:
class HomePageModel
{
public User user { get; set; }
public ResultHistory resultHistory { get; set; }
public Option option { get; set; }
public HomePageModel()
{
}
}
Code from controller when passing it into view:
[FacebookAuthorize]
public async Task<ActionResult> Index(Context context)
{
ViewBag.AppUrl = GlobalFacebookConfiguration.Configuration.AppUrl;
if (ModelState.IsValid)
{
var user = await context.Client.GetCurrentUserAsync<MyAppUser>();
var option = new Option();
//CODE for reading user from db, simpified
Users dbUser = db.Get(context);
var resultHistory = new ResultHistory(dbUser.NSPGW, dbUser.NSPGL,
dbUser.NMPGW,dbUser.NMPGL,dbUser.NDPGW, dbUser.NDPGL);
HomepageModel homepageModel = new HomepageModel();
homepageModel.option = option;
homepageModel.resultHistory = resultHistory;
homepageModel.user = user;
return View(homepageModel);
}
}
Code from controller
#using (Html.BeginForm("Start", "Home", FormMethod.Post, new { id="opcijeForm"}))
{
<div class="row">
<div class="col-md-4">
<div class="radio">
<label>
<input type="radio" name="radio" value="sp" />SP
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="radio" value="mp" />MP
</label>
</div>
<div>
<input type="submit" value="start" />
</div>
</div>
<div class="col-md-8">
<div id="spoption">
#Html.DropDownListFor(m => m.option.sl, Model.option.slSelectList)
<label style="padding-left:10px">
<input type="checkbox" id="bb" /> BB
</label>
#Html.DropDownListFor(m => m.option.swt, Model.option.swtSelectList, new {id="bbdd" })
<label style="padding-left:10px">
<input type="checkbox" id="ziv" /> ziv
</label>
#* #Html.DropDownListFor(m => m.gameOption.sln, Model.option.slnSelectList, new { id="zivdd"})*#
</div>
<div id="mpoption">
<label>Numer of oppointment</label>
#Html.DropDownListFor(m=>m.option.spn, Model.option.spnSelectList)
#Html.DropDownListFor(m=>m.option.smv, Model.option.smvSelectList)
</div>
</div>
</div>
}
and receiving model on post
[FacebookAuthorize]
[HttpPost]
public ActionResult Start(HomepageModel model)
{
//Some code
//here is for example model.option null
}
When I submit form with above model, in my controller action where I receive same model, all it's properties are null.Each class that is within HomePage has only string and int as properties. If I move something, for example from class Option and put it in HomePageModel direct, then properties I have moved are not null. Is there a way to post model as above, or should I just copy properties from these three class into HomePageModel class?
[EDIT]
It is because of meta-data FacebookAuthorize, when I remove it everything is working
MVC app facebook passing object from view to controller at submit

RedirectToAction on [HttpPost] returning "resource not found" error

I have a fairly simple project with is using ninject with asp mvc 4 and entity framework.
I have added an edit and create ActionResult based on the view with no problems. However the delete ActionResult is not working.
The view is a IEnumrable based on the entity, with a simple ActionLink
#Html.ActionLink("Delete", "Delete_Client", new { item.ClientId })
The controller is also very simple.
[HttpPost]
public ActionResult Delete_Client(int id)
{
Client deleteClient = repository.DeleteClient(id);
if (deleteClient != null)
{
TempData["message"] = string.Format("{0} was deleted.", deleteClient.Name);
}
return RedirectToAction("Admin_Client_List");
}
This interacts with the model through the Iinterface
Client DeleteClient(int id);
and in the Entity framework
public Client DeleteClient(int id)
{
Client dbEntry = context.Clients.Find(id);
if (dbEntry != null)
{
context.Clients.Remove(dbEntry);
context.SaveChanges();
}
return dbEntry;
}
The error is
The resource cannot be found.
This is very confusing because i feel like i am not understanding a very fundamental principle of the framework. As i understand it, that means that there is no corresponding ActionResult for the client controller. But there is. The tutorial is am working through suggested that a delete action should be idempotent and therefore only contain a [HttpPost] .
The Uri looks like this
/Client/Delete_Client?ClientId=12
I thought that maybe it would need to look like this
/Client/Delete_Client/12
However that does not work.
Updated request for Admin_Client_List.cshtml
#model IEnumerable<Project.Domain.Entities.Client>
#{
ViewBag.Title = "Client List";
ViewBag.Icon = "entypo-layout";
ViewBag.ClientActive = "active";
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
Create a new Client
<div class="row">
#foreach (var item in Model)
{
<div class="col-sm-3">
<div class="tile-progress tile-blue">
<div class="tile-header">
<a href="#Url.Action("Client_Details", "Client", new { id =item.ClientId})">
<h3>#item.Name <i class="entypo-right-open-big"></i> <span class="badge badge-secondary pull-right">7</span></h3>
</a>
</div>
<div class="tile-progressbar">
<span data-fill="78%" style="width: 78%;"></span>
</div>
<div class="tile-footer">
<h4>
<span class="pct-counter">78</span>% increase
</h4>
<span>#item.Description</span>
</div>
<div class="tile-header">
<a href="#Url.Action("Edit_Client", "Client", new { id = item.ClientId})" type="button" class="btn btn-blue btn-icon icon-left">
<i class="entypo-pencil"></i> Edit
</a>
#*Show Me*#
#Html.ActionLink("Delete", "Delete_Client", new { id = item.ClientId })
#*Delete <i class="entypo-cancel"></i>*#
</div>
</div>
</div>
}
</div>
try with
#Html.ActionLink("Delete", "Delete_Client", null, new { id = item.ClientId })
and you must delete the [HttpPost], this is a GET request
Use the following code:
#Html.ActionLink("Delete", "Delete_Client", new { id = item.ClientId })
[HttpPost]
public ActionResult Delete_Client(int id)
{
Client deleteClient = repository.DeleteClient(id);
if (deleteClient != null)
{
TempData["message"] = string.Format("{0} was deleted.", deleteClient.Name);
}
return RedirectToAction("Admin_Client_List");
}
Change your code
#Html.ActionLink("Delete", "Delete_Client", new { item.ClientId })
to
#Html.ActionLink("Delete", "Delete_Client", new { id = item.ClientId })

Upload in MVC4, got 2 parameters in my action but file is empty

I'm trying to upload a file to a directory. The following code worked for me
CONTROLLER
[HttpPost]
public ActionResult Index(HttpPostedFileBase uploadFile)
{
//string path = #"C:\Users\thomas\Desktop";
if (uploadFile != null)
{
string filePath = Path.Combine(Server.MapPath("/files"), Path.GetFileName(uploadFile.FileName));
uploadFile.SaveAs(filePath);
}
return RedirectToAction("Index");
}
HTML PAGE
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<form action="/Post/Index" method="post" enctype="multipart/form-data">
<label for="uploadFile">Upload file: </label>
<input name="uploadFile" id="uploadFile" type="file" />
<input value="uploadFile" type="submit" />
</form>
Now i'm trying to implement this in a function where i create a message which is created by a model that is containing a message and an item class. When i submit the form the model is passed to my savecontroller but the file is null in my parameter controller.
HTML PAGE
Create new message
#model GeoCitytroopers.Models.MessageItemModel
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Event</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Message.MessagePicture)
</div>
<div>
<label for="uploadFile">Upload file: </label>
<input name="uploadFile" id="uploadFile" type="file" />
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Message.MessagePicture)
#Html.ValidationMessageFor(model => model.Message.MessagePicture)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Item.ItemTitle)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Item.ItemTitle)
#Html.ValidationMessageFor(model => model.Item.ItemTitle)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Item.ItemDescription)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Item.ItemDescription)
#Html.ValidationMessageFor(model => model.Item.ItemDescription)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
CONTROLLER
[HttpPost]
public ActionResult Create(HttpPostedFileBase uploadFile, MessageItemModel ViewModel)
{
if (ModelState.IsValid)
{
Utility ut = new Utility();
Item viewItem = ViewModel.Item;
Message viewMessage = ViewModel.Message;
if (uploadFile != null)
{
string filePath = Path.Combine(Server.MapPath("/files"), Path.GetFileName(uploadFile.FileName));
uploadFile.SaveAs(filePath);
}
//ADD USER TO ITEM
viewItem = ut.AddUserToItem(viewItem);
//ADD ITEM
viewItem.ItemCreateddate = DateTime.Now;
//ADD DISTRICT TO ITEM
viewItem.DistrictID = ut.GetUserDistrict();
db.Items.Add(viewItem);
//ADD LINK
viewMessage.Item = viewItem;
db.Messages.Add(viewMessage);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(ViewModel);
}
How can i pass the uploading file to my controller?
Thanks in advance!
You forgot set the correct enctype to the form. You cannot upload files without that:
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" })) {
...
}
Now the upload will work and your uploadFile parameter will not be null.
My initial guess is that the you created using Html helper doesn't have the necessary encrypt on it.
try using
using(#Html.BeginForm("action-name","controller-name",
FormMethod.Post, new { enctype="multipart/form-data"}){
}
with appropriate values for action-name and controller-name