C# Html.ValidationMessageFor not working when form post - c#

I have an issue with validation messages.
Controller:
[HttpGet]
[Authorize]
public ActionResult Others(string bid)
{
return View(ret);
}
[HttpPost]
public ActionResult OthersUser(Others info)
{
return RedirectToAction("Others", "User", new { bid = "1" });
}
[HttpPost]
public ActionResult OthersPass(Others info)
{
if (ModelState.IsValid)
{
}
return RedirectToAction("Others", "User", new { bid = "2" }); ;
}
Password Confirm Class:
public class PassConfirm
{
[Key]
public int ID { get; set; }
public User User { get; set; }
public virtual int UserID { get; set; }
public string Key { get; set; }
[Required]
public string Password { get; set; }
[NotMapped]
[Compare("Password", ErrorMessage = "Passwords not matching!")]
public string ConfirmPassword { get; set; }
}
Others Class:
public class Others
{
public int BID { get; set; }
public PassConfirm PassChg { get; set; }
public String OldPsw { get; set; }
public User User { get; set; }
public string UserCheck { get; set; }
}
View:
<div style="display: flex; align-items: center;">
#using (Html.BeginForm("OthersPass", "User", FormMethod.Post))
{
<table>
<tr>
<td><label for="oldpsw">Eski Şifre:</label></td>
<td>#Html.TextBoxFor(x => x.OldPsw ,new { #id = "oldpsw", #type = "password" })</td>
</tr>
<tr>
<td><label for="newpsw">Yeni Şifre:</label></td>
<td>#Html.TextBoxFor(x => x.PassChg.Password, new { #id = "newpsw", #type = "password" })</td>
<td>#Html.ValidationMessageFor(x => x.PassChg.Password)</td>
</tr>
<tr>
<td><label for="confpsw">Şifreyi Doğrula:</label></td>
<td>#Html.TextBoxFor(x => x.PassChg.ConfirmPassword, new { #id = "confpsw", #type = "password"})</td>
<td>#Html.ValidationMessageFor(x => x.PassChg.ConfirmPassword)</td>
</tr>
</table>
<button class="btn btn-success" formmethod="post">Onayla</button>
}
</div>
When the user clicked the button with the wrong values, it returns nothing. I think the problem is caused by 2 post method. Maybe because of the values ​​returned by ActionResult elements. So what could be the source of the problem?

Related

ASP.NET MVC get data from another table and link together

I'm creating a system which lists all of data employees and their email and ext etc. I've got this working fine with a search.
Model:
namespace ServiceDirectory.Models
{
[Table("Employee")]
public class Employee
{
[Key]
public int EmployeeID { get; set; }
[DisplayName("First Name")]
public String Forename { get; set; }
[DisplayName("Surname")]
public String Surname { get; set; }
public String Ext { get; set; }
public String Email { get; set; }
public bool Active { get; set; }
}
}
View:
#model IEnumerable<ServiceDirectory.Models.Employee>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm("Index", "Employee", FormMethod.Get))
{
<b>Search By:</b> #Html.RadioButton("searchBy", "Surname", true) <text>Surname</text>
#Html.RadioButton("searchBy", "Forename") <text>ForeName</text><br />
#Html.TextBox("search") <input type="submit" value="Search" />
}
<table class="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Ext</th>
<th scope="col">Job Title & Location</th>
<th scope="col">Email</th>
</tr>
</thead>
#foreach (var Employee in Model)
{
<tr>
<td>#Employee.Forename #Employee.Surname</td>
<td>#Employee.Ext</td>
<td>Job Title here</td>
<td>#Employee.Email</td>
</tr>
}
</table>
Controller:
namespace ServiceDirectory.Controllers
{
public class EmployeeController : Controller
{
private ApplicationDbContext db;
public EmployeeController()
{
db = new ApplicationDbContext();
}
// GET: Employee
public ActionResult Index(string searchBy, string search)
{
if (searchBy == "Forename")
{
return View(db.Employee.Where(x => x.Forename.StartsWith(search)).Where(e => e.Active).ToList());
}
else
{
return View(db.Employee.Where(x => x.Surname.StartsWith(search)).Where(e => e.Active).ToList());
}
}
protected override void Dispose(bool disposing)
{
db.Dispose();
}
}
}
In my view you will see "Job Title here", what I want to do is get the job title to display for each employee, my issue is that its in another table called EmployeeDetails.
How can I link into EmployeeDetails to get the job title and link it into my employee view?
Any help would be appreciated, this is my 1st project :)
First, create a class (view model) something like this below. You would list down the properties you want to display. I name it EmpVM
public class EmpVM
{
public int EmployeeID { get; set; }
public String Forename { get; set; }
public String Surname { get; set; }
public String Ext { get; set; }
public String Email { get; set; }
public bool Active { get; set; }
public String JobTitle { get; set; }
}
Then in your controller you use Linq join to join Employee table and Employee detail and push the result as EmpVM class
public ActionResult Index(string searchBy, string search)
{
List<EmpVM> Employee = new List<EmpVM>();
var Emp = (from E1 in db.Employee
join E2 in db.EmployeeDetail
on E1.EmployeeID equals E2.EmployeeId
select new EmpVM
{
EmployeeID = E1.EmployeeID,
Forename = E1.Forename,
Surname = E1.Surname,
Ext = E1.Ext,
Email = E1.Email,
Active = E1.Active,
JobTitle = E2.JobTitle
});
if (searchBy == "Forename")
{
Emp.Where(a => a.Forename.StartsWith(search) && a.Active == true);
}
else
{
Emp.Where(a => a.Surname.StartsWith(search) && a.Active == true);
}
Employee = Emp.ToList();
return View(Employee);
}
The view will be very simple. You just need to display the collection. It goes like (remember to replace your own namepsace)
#model IEnumerable<Incendo.Web.Models.EmpVM>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#*Your search method here*#
<table class="table table-condensed ">
#foreach (var item in Model)
{
<tr>
<td>#item.Forename #item.Surname</td>
<td>#item.Ext</td>
<td>#item.Email</td>
<td>#item.JobTitle</td>
</tr>
}
</table>
I have not tested it life but I think it should work. Let me know your result.
You can achieve by having a view model. I assume your EmployeeDetail class like below
public class EmployeeDetail
{
public int Id { get; set; }
public int EmployeeId { get; set; }
public string JobDescription { get; set; }
}
Create a ViewModel for the purpose and name it as EmployeeVM
public class EmployeeVM
{
public List<Employee> Employees { get; set; }
public List<EmployeeDetail> EmployeeDetails { get; set; }
}
In your Controller
public ActionResult Index(string searchBy, string search)
{
List<EmpVM> Employee = new List<EmpVM>();
var Emp = (from E1 in db.Employee
join E2 in db.EmployeeDetail
on E1.EmployeeID equals E2.EmployeeId
select new EmpVM
{
EmployeeID = E1.EmployeeID,
Forename = E1.Forename,
Surname = E1.Surname,
Ext = E1.Ext,
Email = E1.Email,
Active = E1.Active,
JobTitle = E2.JobTitle
});
if (searchBy == "Forename")
{
if (!String.IsNullOrEmpty(search))
{
Emp = Emp.Where(a => a.Forename.StartsWith(search) && a.Active == true);
}
}
else
{
if (!String.IsNullOrEmpty(search))
{
Emp = Emp.Where(a => a.Surname.StartsWith(search) && a.Active == true);
}
}
Employee = Emp.ToList();
return View(Employee);
}
In your View
#model IEnumerable<Incendo.Web.Models.EmpVM>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
<b>Search By:</b> #Html.RadioButton("searchBy", "Surname", true)
<text>Surname</text>
#Html.RadioButton("searchBy", "Forename") <text>ForeName</text>
<br />
#Html.TextBox("search")
<input type="submit" value="Search" />
}
<table class="table table-condensed ">
#foreach (var item in Model)
{
<tr>
<td>#item.Forename #item.Surname</td>
<td>#item.Ext</td>
<td>#item.Email</td>
<td>#item.JobTitle</td>
</tr>
}
</table>

Submit ASP.NET CORE MVC Quiz/Exam with different type of choices

I'm working on Online Quiz System.
My models:
EXAM.cs
public Exam()
{
this.Questions = new HashSet<Question>();
}
[Key]
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
public ICollection<Question> Questions { get; set; }
[Required]
public int QuestionsCount { get; set; }
Question.cs
public Question()
{
this.Id = Guid.NewGuid().ToString();
this.Choices = new HashSet<Choice>();
}
[Key]
public string Id { get; set; }
[Required]
public string Text { get; set; }
public ICollection<Choice> Choices { get; set; }
public bool IsActive { get; set; }
[Required]
public int ExamId { get; set; }
[ForeignKey(nameof(ExamId))]
public Exam Exam { get; set; }
Choice.cs
public Choice()
{
this.Id = Guid.NewGuid().ToString();
}
[Key]
public string Id { get; set; }
[Required]
public string QuestionId { get; set; }
[ForeignKey(nameof(QuestionId))]
public Question Question { get; set; }
[Required]
public string Text { get; set; }
[Required]
public bool IsTrue { get; set; }
Answer.cs
public Answer()
{
this.Id = Guid.NewGuid().ToString();
}
[Key]
public string Id { get; set; }
[Required]
public string UserId { get; set; }
[ForeignKey(nameof(UserId))]
public ApplicationUser User { get; set; }
[Required]
public string ChoiceId { get; set; }
[ForeignKey(nameof(ChoiceId))]
public Choice Choice { get; set; }
Each question can have many answers. Every answer can be true or false. If a question has more than one answer that is true, then i use checkboxes (multiple choice), in other case i use radiobuttons (single choice).
Take.cshtml - Exam View
<form method="post" class="form-horizontal">
#foreach (var q in Model.Questions)
{
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-header">
<h3 class="box-title">#(counter +". "+q.Text)</h3>
</div>
<!-- /.box-header -->
<div class="box-body table-responsive no-padding">
<table class="table table-hover">
#{
var trueChoices = q.Choices.Where(c => c.IsTrue == true).Count();
var order = Model.AnswersOrder;
var currentChoices = q.Choices;
}
#if (order == OrderType.Fixed)
{
currentChoices = currentChoices.OrderBy(c => c.CreatedOn).ToList();
}
else
{
currentChoices = examService.GetMixedChoices(currentChoices);
}
#foreach (var choice in currentChoices)
{
<tr>
#if (trueChoices <= 1)
{
<td class="col-xs-2"><input name='asd' value='asd' type="radio" /></td>
}
else
{
<td class="col-xs-2"><input name="asd" value='asd' type="checkbox" /></td>
}
<td class="col-xs-8">#choice.Text</td>
</tr>
}
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
</div>
counter++;
}
<div class="box-footer">
<button id="submitExam" type="submit" class="btn btn-block btn-primary">Submit</button>
</div>
</form>
My question is how can i submit this form? I want to put the information in one table with user id and choice id and to check if the selected choice is correct or not.
Thank you!

MVC on submit getting null object back in controller

I am using Razor with MVC 5,C# and a Model(ClassTestQuestion) that is related with another Model(ClassTestQuestionMc).
I Check some checkboxes and when I press submit button (finish) in controller I am getting back null object.
How I can get back the the results?
In View:
#model IEnumerable<OnlineLearningMVC.Models.ClassTestQuestion>
#using (Html.BeginForm("FinishTest", "ClassTestQuestions", FormMethod.Post))
{
#Html.AntiForgeryToken()
foreach (var item in Model)
{
#Html.DisplayFor(model => item.QuestionTx)
#Html.HiddenFor(model => item.Id)
#Html.HiddenFor(model => item.QuestionTx)
<br/>
<br />
foreach (var Question in item.ClassTestQuestionMc)
{
#Html.DisplayFor(model => Question.AnswerTx)
#Html.HiddenFor(model => Question.AnswerTx)
#Html.CheckBoxFor(model => Question.IsChecked)
#Html.HiddenFor(model => Question.IsChecked)
}
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="FinishTest" class="btn btn-default" />
</div>
</div>
In controller:
public ActionResult ClassCourseTest(int IdCourse)
{
var classTestQuestions = db.ClassTestQuestions.Include(c=>c.ClassTestQuestionMc).Include(c => c.ClassTest).Where(i=>i.ClassTestId== IdCourse);
return View("ClassCourseTest", classTestQuestions.ToList());
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult FinishTest(ClassTestQuestion classTestQuestion)
{
return View(classTestQuestion);
}
My ClassTestQuestion Model:
namespace OnlineLearningMVC.Models
{
public class ClassTestQuestion
{
public int Id { set; get; }
public int ClassTestId { set; get; }
public virtual ClassTest ClassTest { set; get; }
[Required]
[DisplayName("Question")]
public string QuestionTx { set; get; }
[Required]
[DisplayName("Order")]
public int OrderInt { get; set; }
[DisplayName("Disabled")]
public bool IsDeleted { set; get; }
public string CreatedFrom { set; get; }
public DateTime CreatedDate { set; get; }
public string UpdatedFrom { set; get; }
public DateTime UpdatedDate { set; get; }
public virtual ICollection<ClassTestQuestionMc> ClassTestQuestionMc { set; get; }
}
My ClassTestQuestionMc Model:
namespace OnlineLearningMVC.Models
{
public class ClassTestQuestionMc
{
public int Id { set; get; }
public int ClassTestQuestionId { set; get; }
public virtual ClassTestQuestion ClassTestQuestion { set; get; }
[Required]
public string AnswerTx { set; get; }
[DisplayName("Is Correct Answer?")]
public bool IsCorrectAnswer { set; get; }
public bool IsChecked { set; get; }
[DisplayName("Disabled")]
public bool IsDeleted { set; get; }
public string CreatedFrom { set; get; }
public DateTime CreatedDate { set; get; }
public string UpdatedFrom { set; get; }
public DateTime UpdatedDate { set; get; }
}
What I see in Browser:
Edit
I have try to change to IEnumerable :
Change ICollection to IList for ClassTestQuestionMc. Then you need to follow array name convention here to make MVC work to handle the view model.
foreach (int i = 0; i < Model.Count; i++)
{
#Html.DisplayFor(model => Model[i].QuestionTx)
#Html.HiddenFor(model => Model[i].Id)
#Html.HiddenFor(model => Model[i].QuestionTx)
<br/>
<br/>
foreach (int j = 0; j < Model[i].ClassTestQuestionMc; j++)
{
#Html.DisplayFor(model => Model[i].ClassTestQuestionMc[j].AnswerTx)
#Html.HiddenFor(model => Model[i].ClassTestQuestionMc[j].AnswerTx)
#Html.CheckBoxFor(model => Model[i].ClassTestQuestionMc[j].IsChecked)
#Html.HiddenFor(model => Model[i].ClassTestQuestionMc[j].IsChecked)
}
}

ViewModel with foreign key and Create action

I have a page that show details of a post and Identified users can add commented on that post.
My problems:
PostID and UserID is FK in Comment model and don't pass from view to controller
CommnetMessage is Null!!
what is wrong?
Comment Model :
public class Comment : System.Object
{
public Comment()
{
this.CommnetDate = General.tzIran();
}
[Key]
public int CommentID { get; set; }
[Required]
public string CommnetMessage { get; set; }
[Required]
public DateTime CommnetDate { get; set; }
public string UserId { get; set; }
[Key, ForeignKey("UserId")]
public virtual ApplicationUser ApplicationUser { get; set; }
public int PostID { get; set; }
[Key, ForeignKey("PostID")]
public virtual Post posts { get; set; }
}
Post Model:
public class Post : System.Object
{
public Post()
{
this.PostDate = General.tzIran();
this.PostViews = 0;
}
[Key]
public int PostID { get; set; }
public string PostName { get; set; }
public string PostSummery { get; set; }
public string PostDesc { get; set; }
public string PostPic { get; set; }
public DateTime PostDate { get; set; }
public int PostViews { get; set; }
public string postMetaKeys { get; set; }
public string PostMetaDesc { get; set; }
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser ApplicationUser { get; set; }
public int CategoryID { get; set; }
[ForeignKey("CategoryID")]
public virtual Category Category { get; set; }
public virtual ICollection<Comment> commnets {get; set;}
}
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
/*Realations*/
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
View Model:
public class PostViewModel
{
public ApplicationUser Users { get; set; }
public Post posts { get; set; }
public Category Categories { get; set; }
public IEnumerable<Comment> ListCommnets { get; set; }
public Comment Commnets { get; set; }
}
Controller:
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var post = db.Posts.Find(id);
post.PostViews += 1;
db.SaveChanges();
if (post == null)
{
return HttpNotFound();
}
return View(new PostViewModel() { posts = post });
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details([Bind(Include = "CommentID,CommnetMessage,CommnetDate,UserId,PostID")] Comment comment , int? id)
{
int pid = comment.PostID;
if (ModelState.IsValid)
{
db.CommentS.Add(comment);
db.SaveChanges();
TempData["notice"] = "پیغام شما با موفقیت ثبت شد.";
return RedirectToAction("success");
}
ViewBag.UserId = new SelectList(db.Users, "Id", "FirstName", comment.UserId);
ViewBag.PostID = id;
return View( new PostViewModel() { posts = db.Posts.Find(id)});
}
public ActionResult success()
{
ViewBag.Message = "از طریق فرم زیر می توانید برایمان پیغام بگذارید.";
return View("Details", new PostViewModel() { ListCommnets = db.CommentS });
}
Comment Partial View:
#using Microsoft.AspNet.Identity
#using FinalKaminet.Models
#using Microsoft.AspNet.Identity.EntityFramework
#model FinalKaminet.ViewModel.PostViewModel
#if (TempData["notice"] != null)
{
<p>#TempData["notice"]</p>
}
#if (Request.IsAuthenticated)
{
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var user = manager.FindById(User.Identity.GetUserId());
using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.posts.PostID)
#Html.HiddenFor(model => model.Users.Id)
<div class="form-group">
#Html.LabelFor(model => model.Users.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#{
var name = user.FirstName + " " + user.LastName;
}
<input type="text" id="Id" value="#name" disabled="disabled" class="form-control" />
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Commnets.CommnetMessage, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Commnets.CommnetMessage, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Commnets.CommnetMessage, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Send" class="btn btn-default" />
</div>
</div>
</div>
}
}
else
{
<p>#Html.ActionLink("Log in", "Login", "Account", new { returnUrl = Request.Url }, null)</p>
}
As #StephenMuecke stated, model of your view is PostViewModel and all editors, hidden fields are created based on your view model. For example, when you generate hidden field using #Html.HiddenFor(model => model.posts.PostID) and try to post your data MVC model binder tries to bind the value of this field to the model specified at your Action method. In your case it is Comment so , MVC model binder will try bind value of generated hidden field to Comment.posts.PostID which does not exist. To make everything work perfectly you have to use same view model as a argument of your action method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details(PostViewModel viewModel)
{
......
}
Also, again as #StephenMuecke sated, your view model should have only those properties which you need. For example, your PostViewModel should look like something as following:
public class PostViewModel
{
// Actually, you do not need UserId property
// as it should be retrieved inside controller
// from current user data
public string UserId { get; set; }
public string UserName { get; set; }
public int PostID { get; set; }
public string CommentMessage { get; set; }
}
Back to your action method, you have to map view model to your model:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details(PostViewModel viewModel)
{
Comment comment = new Comment
{
CommnetMessage = viewModel.CommentMessage,
// and other properties
}
// Save your model and etc.
}

Passing parameters on button click in strongly-typed view to another controller

I have a strongly-typed view (bound to userController) which lists the User with particular Roles and below that I have a dropdownlist containing all the Roles with a submit button. All I need is to assign new Role to that User. The ActionResult method is in UserRolesController. how can i pass userId and RoleId on button click to ActionResult Method.
ActionResult Method in UserRolesController:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddRole(UserRole userRole, int roleId, int userId)
{
if (!ModelState.IsValid) return View(userRole);
var check = db.UserRoles.Any(x => x.RoleID == roleId && x.UserID == userId);
if (check)
ViewBag.ResultMessage = "This user already has the role specified !";
else
db.UserRoles.Add(userRole);
db.SaveChanges();
ViewBag.ResultMessage = "User added to the role succesfully !";
return RedirectToAction("Index");
}
View like this:
#model IEnumerable<MvcAppCRUD.user>
#{
ViewBag.title = "AssignRole";
}
<h2>Assign Role</h2>
#if (!Model.Any())
{
#Html.Label("No Roles assigned for this user")
}
else
{
<table>
<tr>
<th>
#Html.DisplayName("Email")
</th>
<th>
#Html.DisplayName("Role Name")
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.email)
</td>
<td>
#Html.DisplayFor(modelItem => item.RoleName)
</td>
<td>
#Html.ActionLink("Delete", "Delete", new {id = item.id})
</td>
</tr>
}
</table>
}
<hr />
<div class="display-label">
#Html.DisplayName("Add Role")
</div>
<div class="display-field">
#Html.DropDownList("Roles", (SelectList) ViewBag.Roles)
</div>
#using (Html.BeginForm("AddRole", "UserRoles"))
{
<div class="message-success">#ViewBag.ResultMessage</div>
}
<p>
<input type="submit" value="Assign" />
</p>
<p>
#Html.ActionLink("Back to List", "Index")
</p>
Model Entities:
public partial class UserRole
{
public int ID { get; set; }
public int UserID { get; set; }
public int RoleID { get; set; }
public int Status { get; set; }
public virtual user Users { get; set; }
public virtual Role Roles { get; set; }
}
public partial class user
{
public user()
{
Roles = new List<SelectListItem>();
}
public long id { get; set; }
public string email { get; set; }
public string password { get; set; }
public System.DateTime reg_date { get; set; }
public byte validated { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
public int RoleId { get; set; }
public string RoleName { get; set; }
public IEnumerable<SelectListItem> Roles { get; set; }
//public IEnumerable<Role> Roles { get; set; }
}
public partial class Role
{
public int ID { get; set; }
public string RoleName { get; set; }
public string Desc { get; set; }
public int Status { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}
On Button click nothing happens. Is is possible to pass the values as parameters from one model view to another?
There are numerous problems with you code. In particular your passing IEnumerable<user> to the model not including or rendering any controls in your form so nothing posts back, and in any case you cant post back UserRole because its a complex object and a dropdownlist only returns a single value. And there is no point displaying all roles in the dropdown, then checking if its already been selected on postback - just include only those roles that the user does not already have when you create the view. And assigning a message to ViewBag and then redirecting is pointless - its immediately lost.
Create a view model to represent what you want to display and edit (note I have excluded properties for displaying existing roles)
public class UserRoleVM
{
public int ID { get; set; } // user ID for post back
public int Name { get; set; } // user name for display in the view
[Display(Name="Select new role")]
public int SelectedRole { get; set; }
public SelectList RoleList { get; set; }
}
Controller
public ActionResult AddRole(int ID)
{
UserRoleVM model = new UserRoleVM();
var user = // Get the user based on the ID
model.ID = ID;
model.Name = user.??
var roles = // Get all roles and remove those that the user already has
model.RoleList = new SelectList(roles, "ID", "RoleName");
return View(model);
}
View
#model UserRoleVM
#using(Html.BeginForm())
{
<h2>#Model.Name</h2> // users name
#Html.LabelFor(m => m.SelectedRole)
#Html.DropDownListFor(m => m.SelectedRole, Model.RoleList)
<input type="submit" value="Add Role" />
}
Post method
[HttpPost]
public ActionResult AddRole(UserRoleVM model)
{
// model is now populated with the ID of the user and the ID of the selected role
// save and redirect
}

Categories

Resources