how to use role in mvc identity 2.1.0 - model-view-controller

I want to introduce the identity role to my login page .the user after entering username and password should select a dropdownlist of roles (superuser-admin-user).how could that happen?

Create a class to manage roles, that would be something like ApplicationRoleManager
public class ApplicationRoleManager : RoleManager<IdentityRole, string>
{
public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
: base(roleStore)
{
}
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
return new ApplicationRoleManager(new RoleStore<IdentityRole, string, IdentityUserRole>(context.Get<ApplicationDbContext>()));
}
}
Then you need to create instance of ApplicationRoleManager on owin startup. Add below code inside the ConfigureAuth method on Owin startup. App_Start >> Startup.Auth.cs
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
Now you have all setup for manage your roles. Make sure you have added roles to your 'AspNetRoles' table
Then you can retrieve roles as below inside the Login (Get) action
// GET: /Account/Login
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
var roleManager = HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
var roles = roleManager.Roles.ToList();
var list = new SelectList(roles, "Id", "Name");
ViewBag.Roles = list;
ViewBag.ReturnUrl = returnUrl;
return View();
}
Then you can get roles in the Login view. After that populate dropdownList with roles. Your rasor script will look like below.
#using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Use a local account to log in.</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<label id="RoleDdlLabel" class="col-md-2 control-label">Select Role</label>
<div class="col-md-10">
#Html.DropDownList("RoleList", ViewBag.Roles as SelectList)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
#Html.CheckBoxFor(m => m.RememberMe)
#Html.LabelFor(m => m.RememberMe)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
<p>
#Html.ActionLink("Register as a new user", "Register")
</p>
#* Enable this once you have account confirmation enabled for password reset functionality
<p>
#Html.ActionLink("Forgot your password?", "ForgotPassword")
</p>*#
}
I hope you can finish the saving part by posting the selected role with other model values. You can change the LoginViewModel to include roles.
Hope this helps.

Related

MVC validation focusing the date time control on validation fail

I am having my view as follows
#using (Html.BeginForm("Apply", "Leave", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="form-group">
Leave Type
#Html.DropDownListFor(m => m.LeaveTypeId, Model.LeaveType, "Choose...", new { #class = "form-control", #tabindex = "1" })
#Html.ValidationMessageFor(m => m.LeaveTypeId, "", new { #class = "label-danger" })
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="form-group">
From Date
#Html.TextBoxFor(m => m.FromDate, new { #class = "form-control", #tabindex = "2" })
#Html.ValidationMessageFor(m => m.FromDate, "", new { #class = "label-danger" })
</div>
</div>
}
When I click on apply button it is auto focusing the next control as my tab index was set. So is there any way to focus but not display the datetime control

MVC5 Ajax.BeginForm, UpdateTargetId no render PartialView

I have a problem with my MVC application.
My controller:
public class CustomerController : Controller
{
CustomerFacade cf = new CustomerFacade();
public ActionResult Create()
{
return View();
}
[HttpPost]
public void Create(Customers customers)
{
if (customers != null)
{
cf.CreateCustomer(customers, UserSession.UserId);
}
// return View();
}
public ActionResult GetAllCustomers()
{
var allCustomers = cf.GetAllCustomers();
return PartialView("InsuranceCustomer", allCustomers);
}
}
My main view:
<div class="x_content">
<div id="mainb" style="height:350px;">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target=".bs-example-modal-lg">
<i class="fa fa-plus"></i>
</button>
#*render modal*#
#Html.Partial("~/Views/Customer/CreateModal.cshtml")
<button type="button" class="btn btn-primary" data-toggle="modal" data-target=".bs-example-modal-lg">
<i class="fa fa-database"></i>
</button>
#*render modal*#
<div id="customerId">
#Html.Action("GetAllCustomers", "Customer")
</div>
</div>
</div>
The partial view CreateModal.cshtml is a form on bootstrap modalpopup:
for example:
<div class="modal-body">
#using (Ajax.BeginForm("Create", "Customer", null, new AjaxOptions
{
HttpMethod = "Post",
UpdateTargetId = "customerId",
OnSuccess = "$('#customerModal').modal('hide')"
}))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="col-md-4">
#Html.TextBoxFor(model => model.FirstName, new { #required = "require", #class = "form-control", placeholder = #Resources.InsuranceCustomer.FirstName })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
<div class="col-md-4">
#Html.TextBoxFor(model => model.LastName, new { #required = "require", #class = "form-control", placeholder = #Resources.InsuranceCustomer.LastName })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
// and other field form
<div class="modal-footer">
<button type="submit" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" value="#Resources.Common.Save" class="btn btn-success" />
</div>
}
#*<div>
#Html.ActionLink("Back to List", "Index")
</div>*#
</div>
and InsuranceCustomer looks like:
#model IEnumerable<Insurance_System.Models.Customers>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstName)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
</tr>}
I want to after submiting modal CreateModal loaded again InsuranceCustomer with new element without reloading page.
(sorry for my bad English)
in the controller
public ActionResult Create()
{
return View();
}
[HttpPost]
public void Create(Customers customers)
{
var cust = new customer
{
name=customers.name,
etc....
}
db.customers.add(cust);
db.savechanges();
var listcustomers = db.customers.ToList();
return PartialView("InsuranceCustomer",listcustomers);
}
in the View
<div class="x_content">
<div id="mainb" style="height:350px;">
<div id="customerId">
#*here will be load your partialview*#
</div>
</div>
</div>
<div class="modal-body">
#using (Ajax.BeginForm("Create", "Customer", null, new AjaxOptions
{
HttpMethod = "Post",
UpdateTargetId = "customerId",
OnSuccess = "$('#customerModal').modal('hide')"
}))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="col-md-4">
#Html.TextBoxFor(model => model.FirstName, new { #required = "require", #class = "form-control", placeholder = #Resources.InsuranceCustomer.FirstName })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
<div class="col-md-4">
#Html.TextBoxFor(model => model.LastName, new { #required = "require", #class = "form-control", placeholder = #Resources.InsuranceCustomer.LastName })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
// and other field form
<div class="modal-footer">
<button type="submit" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" value="#Resources.Common.Save" class="btn btn-success" />
</div>
}
#*<div>
#Html.ActionLink("Back to List", "Index")
</div>*#
</div>
in the partial view
#model IEnumerable<Insurance_System.Models.Customers>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstName)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
</tr>}

I'm trying to send two parameters from view to controller but the second is always null

I'm trying to send two parameters (HttpPostedFileBase and the model) from the view to the Create method in the controller but the variable HttpPostedFile photos always gets null values.
Here is the Controller Code:
public async Task <ActionResult> Create([Bind(Include =
"Id,Name,Description")] Models.Environment environment, HttpPostedFileBase photos)
{
if (ModelState.IsValid)
{
if (photos!=null)
{
DataBlobImage dataBlobImage = new DataBlobImage();
environment.Logo = await
dataBlobImage.CreateImage("environment",
environment.Id.ToString(), photos);
}
//Creation date
environment.CreationDate = DateTime.Now;
//Get the creation user ID
environment.CreationUser = 1;
//By default when you create a user is active
environment.Active = true;
db.Environment.Add(environment);
await db.SaveChangesAsync();
return Json(new { success = true });
}
return View(environment);
}
View code:
#using (Html.BeginForm("ModalCreate", "Environment",
FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="modal-header create-window">
<button type="button" class="close"
data-dismiss="modal" aria- hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Crear nuevo Ambiente</h4>
</div>
<div class="modal-body">
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<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 { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "",
new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Description,
htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Description,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Description, "",
new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<label for="file">Subir Imagen:</label>
<input id="photos" name="photos" type="file"
style="width: 100%;" />
</div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal">Cancelar</button>
<input class="btn btn-primary" type="submit" value="Crear" />
</div>
</div>
</div>
}
I think you don't need to pass an additional parameter for that. You can alway access it like below inside your action method:
HttpPostedFileBase file = Request.Files["NameOfYourFileUploadControl"];
Hope this will help.

Show only server side errors in validation summary

I have the following view:
#model MyProject.Models.RegisterViewModel
<div class="content">
<div class="wrapper">
<h2>E-Bill Saver Registration</h2>
<hr />
<div class="columns top-gap">
<div class="first cell width-6 dark-blue-headings">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#*#Html.ValidationSummary("", new { #class = "text-danger" })*#
<div class="form-horizontal">
<div class="form-group">
#Html.Label("Account Number", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.AccountNo, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.AccountNo, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
#Html.Label("MPNumber", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.MPNumber, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.MPRN, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
#Html.Label("Email Address", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.Email, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
#Html.Label("Confirm Email Address", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.ConfirmEmail, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.ConfirmEmail, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
#Html.Label("Password", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.Password, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
#Html.Label("Confirm Password", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.ConfirmPassword, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Register" class="opc_button" />
</div>
</div>
</div>
}
</div>
</div>
</div>
If there are validation errors on any of the fields then the error message is displayed below the label as expected and wanted. On my controller however I have some custom logic errors and I am adding them to the modelstate as follows:
else
{
//This email address is already assigned to a user
ModelState.AddModelError("Email Address : ", "Error! You must enter an email address that is unique to your account.");
return View(model);
}
If I uncomment the validationsummary on my page then it will display the custom server side error but it will also display the single validation errors which I want underneath the labels. Is there any way that I can set the validation summary to ignore the values that are being listed individually and only return server side validation errors?
The first string parameter of ModelState.AddModelError method is the key later used to bind the message to the model property.
If you want to display that error message next to email label, make first parameter of AddModelError match your property name:
ModelState.AddModelError("Email", "Error! Email already used...");

Model binding doesn't work when multiple instances of the same partial view are called dynamically with ajax.actionlink in MVC 5

I'm building a restaurant reservations system. When the user creates a reservation they can also decided what furniture will be used with the reservation. For this I created a partial view, so every time the user click on "add furniture" the partial view is loaded with ajax where the user can then specify what furniture and how many. They can add as many types of furniture as they want, meaning they can call the partial view as many times as they want. My problem comes in with the model binder, the model binder then have bind all those partial view instances to a list object of type "BistroReservations_ReservationsFurniture". Please help how to make the model binder work.
MainView (Please have a look at the bottom for the ajax.actionlink call "Add Furniture"
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>BistroReservations_Reservation</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.DateOfArrival, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DateOfArrival, new { htmlAttributes = new { #class = "form-control datecontrol" } })
#Html.ValidationMessageFor(model => model.DateOfArrival, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BistroReservations_ShiftID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("BistroReservations_ShiftID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BistroReservations_ShiftID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BistroReservations_GuestID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-6">
#Html.DropDownList("BistroReservations_GuestID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BistroReservations_GuestID, "", new { #class = "text-danger " })
#Ajax.ActionLink("Create a New Guest", "NewGuest", new AjaxOptions
{
HttpMethod = "GET",
UpdateTargetId = "NewGuest",
InsertionMode = InsertionMode.ReplaceWith,
})
</div>
</div>
<div id="NewGuest" class="form-group">
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.ArrivalTime, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("ArrivalTime", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ArrivalTime, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LocationID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("LocationID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.LocationID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BistroReservations_TypeOfSeatingID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("BistroReservations_TypeOfSeatingID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BistroReservations_TypeOfSeatingID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TableNoID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("TableNoID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.TableNoID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BistroReservations_StatusID, "BistroReservations_StatusID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("BistroReservations_StatusID",null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BistroReservations_StatusID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Comment, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor( model => model.Comment, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Comment, "", new { #class = "text-danger" })
#Ajax.ActionLink("Add Furniture", "Furniture", new AjaxOptions
{
HttpMethod = "GET",
UpdateTargetId = "Furniture",
InsertionMode = InsertionMode.InsertAfter
})
</div>
</div>
<div id="Furniture" class="form-group">
</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>
}
ActionResult returning the furniture partial view
public PartialViewResult Furniture()
{
ViewBag.BistroReservations_FurnitureID = new SelectList(db.BistroReservations_Furnitures, "BistroReservations_FurnitureID", "Description");
return PartialView("_Furniture");
}
Furniture partial view
#model CdvPortal.Models.BistroReservations.BistroReservations_ReservationFurniture
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.BistroReservations_FurnitureID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("BistroReservations_FurnitureID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BistroReservations_FurnitureID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group ">
#Html.LabelFor(model => model.Quantity, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Quantity, "", new { #class = "text-danger" })
</div>
</div>
</div>
Furniture Model
public class BistroReservations_ReservationFurniture
{
public int BistroReservations_ReservationFurnitureID { get; set; }
public int BistroReservations_ReservationID { get; set; }
public virtual BistroReservations_Reservation BistroReservations_Reservation { get; set; }
[Display(Name="Furniture Type")]
public int BistroReservations_FurnitureID { get; set; }
public virtual BistroReservations_Furniture BistroReservations_Furniture { get; set; }
public int Quantity { get; set; }
}
You #Ajax.ActionLink() method is returning views with duplicate id attributes (invalid html) and duplicate name attributes which are not prefixed with the correct property name and do not include indexers for binding to a collection. For example if the collection property is named FurnitureItems then the html needed for the Quantity property of typeof BistroReservations_ReservationFurniture would need to be
<input type="text" name="FurnitureItems[0].Quantity" ...>
<input type="text" name="FurnitureItems[1].Quantity" ...>
You can use the BeginCollectionItem helper to generate the controls, which might look like (assuming the property is named FurnitureItems)
#model CdvPortal.Models.BistroReservations.BistroReservations_ReservationFurniture
#using (Html.BeginCollectionItem("FurnitureItems"))
{
....
#Html.LabelFor(m => m.Quantity, ..)
#Html.EditorFor(m => m.Quantity, ..)
#Html.ValidationMessageFor(m => m.Quantity, ..)
}
This will generate the correct prefix and add include an indexer based on a guid which also allows you to delete items from the collection. This article explains the usage in more detail
A pure client side alternative is shown in this answer. This gives better performance, but is harder to maintain since changing anything in the BistroReservations_ReservationFurniture model means updating the client side template.

Resources