I have WebAPI based project. It has an API for user registration. RegistrationModel looks as below.
public class RegistrationTO
{
[Required(ErrorMessage="Email required")]
public string Email { get; set; }
[Required(ErrorMessage="Name required")]
public string Name { get; set; }
[Required(ErrorMessage="Surname required")]
public string Surname { get; set; }
}
API
public string Post([FromBody]RegistrationTO model)
{
if (ModelState.IsValid)
{
//actual stuff
}
else
{
return "all * marked fields are required";
}
}
My requirement if model have Email as null, I should return message
"email required", if Name is null then "Name required" & so on.
Yes,one patchy way would be :-
public string Post([FromBody]UserRegistrationTO model)
{
if (ModelState.IsValid)
{
//actual stuff
}
else
{
if(model.Email == null)
return "Email required";
else if(model.Name == null)
return "name required"; // & so on.
}
}
Is there any other simple way to do this??
try do that:
if (ModelState.IsValid)
{
// do something
}
else
return "The following errors happen: \n" +
ModelState.SelectMany(s => s.Value.Errors)
.Select(s => s.ErrorMessage)
.Aggregate((seed, currentValue) => seed += "\n" + currentValue);
I hope it can help you.
You can do this at the view itself.
For individual properties :
#Html.ValidationMessageFor(x => x.Email, null, new { #class = "text-danger" })
and for all failed validation
#if (!ViewData.ModelState.IsValid)
{
<div class="alert alert-danger">
#Html.ValidationSummary(false)
</div>
}
Related
I tried to create an Edit action based on another controller.
But in this particular case, I can't do it.
I don't use a separate model for my post replies, but keep it based on the post ID.
This is what I tried
[Get] Edit method from controller:
[Authorize]
[HttpGet]
public IActionResult Edit(int id)
{
var userId = _userManager.GetUserId(HttpContext.User);
if (userId == null)
{
return View("AccessDenied");
}
var rep = _context.PostReplies.Find(id);
if (rep == null)
{
ViewBag.ErrorMessage = $"Post with ID = {rep} cannot be found";
return View("NotFound");
}
PostReply reply = _context.PostReplies.Find(rep);
if (reply == null)
{
return View("NotFound");
}
if (userId == reply.User.Id || User.IsInRole("Admin") || User.IsInRole("Mod"))
{
return View(reply);
}
else
{
return View("NotFound");
}
}
[Post] Edit method:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit([Bind(include: "Id, Content, Created, Updated")] PostReply reply)
{
if (ModelState.IsValid)
{
_context.Entry(reply).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
_context.SaveChanges();
return RedirectToAction("Manage");
}
return View(reply);
}
This is "model" PostReply:
using System;
namespace collector_forum.Data.Models
{
public class PostReply
{
public int Id { get; set; }
public string Content { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual Post Post { get; set; }
}
}
Which is declarated in my ApplicationDbContext
public DbSet<PostReply> PostReplies { get; set; }
This is my part of HTML code resposible for displaying post replies.
#if (Model.Replies.Any())
{
foreach (var reply in Model.Replies)
{
<div class="row replyContent">
<div class="col-md-3 replyAuthorContainer">
<a class="userName" asp-controller="Profile" asp-action="Detail" asp-route-id="#reply.AuthorId">
#reply.AuthorName
</a>
#if (reply.IsAuthorAdmin && Model.IsAuthorMod)
{
<div class="isAdmin smaller">Admin</div>
}
else if (reply.IsAuthorMod)
{
<div class="isMod smaller">Mod</div>
}
<br />
<span class="postDate">#reply.Date</span>
</div>
<div class="col-md-9 replyContentContainer">
<div class="postContent">
#Html.Raw(reply.ReplyContent)
</div>
</div>
#if (Model.AuthorName.Contains(User.Identity.Name) || User.IsInRole("Admin"))
{
<span class="col-auto">
<a asp-controller="Reply" asp-action="Edit" asp-route-id="#reply.Id" class="btn btn-editPost">
Edit Reply
</a>
</span>
}
else if (Model.AuthorName.Contains(User.Identity.Name))
{
<form asp-action="Delete" asp-controller="Reply" asp-route-id="#reply.Id" method="post">
<button type="submit" class="btn btn-danger"
onclick="return confirm('Are you sure you want to delete post: #Model.Title')">
Delete
</button>
</form>
}
</div>
}
}
With the current code after clicking "Edit" this error shows up
And here my question arises, is it possible to implement this action in a different way?
//EDIT
Problem is that the function "Find" doesn't find other values except "Id", "Content", "Created", "Updated". To let logged user to edit his own reply I need to get user details and post details ex. userId, UserName, postId.. etc.
This are values of properties - image
You can change your Edit Action like this:
[Authorize]
[HttpGet]
public IActionResult Edit(int id)
{
var userId = _userManager.GetUserId(HttpContext.User);
if (userId == null)
{
return View("AccessDenied");
}
var rep = _context.PostReplies.Find(id);
if (rep == null)
{
ViewBag.ErrorMessage = $"Post with ID = {rep} cannot be found";
return View("NotFound");
}
if (userId == rep.User.Id || User.IsInRole("Admin") || User.IsInRole("Mod"))
{
return View(rep);
}
else
{
return View("NotFound");
}
}
You have got rep with _context.PostReplies.Find(id);,So you don't need to use PostReply reply = _context.PostReplies.Find(rep);, and check if it is null again,also you need to put an int type rather than PostReply into _context.PostReplies.Find(xxx).
public async Task<IActionResult> Update(int? id)
{
ViewBag.Positions = new SelectList(_context.Positions, nameof(Position.Id), nameof(Position.Name));
var employee =await _context.Employees.FirstOrDefaultAsync(x => x.Id == id);
if (employee == null) { return NotFound(); }
UpdateEmployeeVM employeeVM = new UpdateEmployeeVM
{
Name = employee.Name,
Surname = employee.Surname,
PositionId = employee.PositionId,
FacebookUrl = employee.FacebookUrl,
TwitterUrl = employee.TwitterUrl,
InstagramUrl = employee.InstagramUrl,
Salary = employee.Salary,
ImgUrl=employee.ImageUrl
};
return View(employeeVM);
}
I'm following a Book which shows you how to edit a users role. Everything's working fine until I get to a line of code. I think it will be a pretty simple solution, however, I cannot figure it out.
var result = await _userManager.AddToRoleAsync(user.Id,
selectedRole.Except(userRoles).ToArray<string>());
The line of code above is returning an error:
"Argument 2: cannot convert from 'string[]' to 'string'"
In the book, it shows:
.ToArray<string>
However, in my line of code, it's just telling me to refactor to:
.ToArray());
Is there another way of converting to string? I'll post the code below, thanks.
EDIT USER CODE
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> EditUser(EditUserViewModel model, params string[] selectedRole)
{
if (ModelState.IsValid)
{
var user = await _userManager.FindByIdAsync(model.Id);
if (user == null)
{
return HttpNotFound();
}
user.UserName = model.UserName;
user.FirstName = model.FirstName;
user.LastName = model.LastName;
var userRoles = await _userManager.GetRolesAsync(user.Id);
selectedRole = selectedRole ?? new string[] { };
var result = await _userManager.AddToRoleAsync(user.Id,
selectedRole.Except(userRoles).ToArray<string>()); // may not be right
if (!result.Succeeded)
{
ModelState.AddModelError("", result.Errors.First());
return View();
}
result = await _userManager.RemoveFromRoleAsync(user.Id, userRoles.Except(selectedRole).ToArray().ToString()); // put to string
if (!result.Succeeded)
{
ModelState.AddModelError("", result.Errors.First());
return View();
}
return RedirectToAction("Index");
}
ModelState.AddModelError("", "Something's failed.");
return View();
}
EditUserViewModel
public class EditUserViewModel
{
public string Id { get; set; }
[Required]
[Display(Name = "Username")]
public string UserName { get; set; }
[Required(AllowEmptyStrings = false)]
[Display(Name = "Email")]
[EmailAddress]
public string Email { get; set; }
[Required]
[Display(Name = "First Name")]
[StringLength(50)]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
[StringLength(50)]
public string LastName { get; set; }
public IEnumerable<SelectListItem> RolesList { get; set; }
}
EditUser View
<div class="form-group">
#Html.Label("Roles", new { #class = "control-label col-md-2" })
<span class="col-md-10">
#foreach (var item in Model.RolesList)
{
<input type="checkbox" name="SelectedRole" value="#item.Value"
checked="#item.Selected" class="checkbox-inline" />
#Html.Label(item.Value, new { #class = "control-label" })
}
</span>
</div>
If you want to convert to string you can use String.Join and as a separator use
string.Empty, null or whatever separator you want but will be included in your string.
string str = string.Join(string.Empty, yourArray)
It's a typo in the book or when copying from the book. It should be:
var result = await _userManager.AddToRolesAsync(user.Id,
selectedRole.Except(userRoles).ToArray<string>());
The AddToRolesAsync takes an IEnumerable<string> as its second parameter, AddToRoleAsync takes a string.
I'm having trouble finding a tutorial / video that shows how to implement Cascading DropDownList from a Database using EntityFramework. I'm using ASP.NET MVC Core, EntityFramework Core with C#.
As of now, I'm able to retrieve the data from my database to my 3 DropDownList fine.
What I would like to be able to accomplish is to have the user select a State first which would then display all Cities related to that State. Then after user has selected a City it would display the Zip Code(s) related to the City.
Any help would be greatly appreciated.
Models
public class Customer
{
public int CustomerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int StateId { get; set; }
public int CityId { get; set; }
public int ZipId { get; set; }
public State State { get; set; }
public City City { get; set; }
public Zip Zip { get; set; }
}
public class State
{
public int StateId { get; set; }
public string Abbr { get; set; }
public List<Customer> Customers { get; set; }
}
public class City
{
public int CityId { get; set; }
public string Name { get; set; }
public int StateId { get; set; }
public State State { get; set; }
public List<Customer> Customers { get; set; }
}
public class Zip
{
public int ZipId { get; set; }
public string PostalCode { get; set; }
public int CityId { get; set; }
public City City { get; set; }
public List<Customer> Customers { get; set; }
}
ViewModels
public class CustomerFormVM
{
public int CustomerId { get; set; }
[Display(Name = "First Name")]
[StringLength(50)]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
[StringLength(50)]
public string LastName { get; set; }
[Required(ErrorMessage = "Select State")]
[Display(Name = "State")]
public int StateId { get; set; }
//public IEnumerable<State> States { get; set; }
public IEnumerable<SelectListItem> States { get; set; }
[Required(ErrorMessage = "Select City")]
[Display(Name = "City")]
public int CityId { get; set; }
//public IEnumerable<City> Citys { get; set; }
public IEnumerable<SelectListItem> Citys { get; set; }
[Required(ErrorMessage = "Select Zip")]
[Display(Name = "Zip")]
public int ZipId { get; set; }
//public IEnumerable<Zip> Zips { get; set; }
public IEnumerable<SelectListItem> Zips { get; set; }
}
CustomerController
public class CustomerController : Controller
{
private MultiDbContext db;
public CustomerController(MultiDbContext context)
{
db = context;
}
// GET: /<controller>/
public IActionResult Index()
{
return View(db.Customers.ToList());
}
public IActionResult getCititesFromDatabaseByStateId(int id)
{
return View(db.Citys.Where(c => c.StateId == id).ToList());
}
public IActionResult getCities(int id)
{
var cities = new List<City>();
cities = getCititesFromDatabaseByStateId(id); //call repository
return Json(cities);
}
public ActionResult Create()
{
var states = db.States.ToList();
var citys = db.Citys.ToList();
var zips = db.Zips.ToList();
var viewModel = new CustomerFormVM
{
States = states,
Citys = citys,
Zips = zips
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CustomerFormVM vm)
{
if (ModelState.IsValid)
{
var customer = new Customer();
{
customer.FirstName = vm.FirstName;
customer.LastName = vm.LastName;
customer.StateId = vm.StateId;
customer.CityId = vm.CityId;
customer.ZipId = vm.ZipId;
}
db.Customers.Add(customer);
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
vm.States = db.States.ToList();
vm.Citys = db.Citys.ToList();
vm.Zips = db.Zips.ToList();
return View(vm);
}
}
public ActionResult Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var customervm = new CustomerFormVM();
{
Customer customer = db.Customers.SingleOrDefault(c => c.CustomerId == id);
if (customer == null)
{
return NotFound();
}
customervm.CustomerId = customer.CustomerId;
customervm.FirstName = customer.FirstName;
customervm.LastName = customer.LastName;
// Retrieve list of States
var states = db.States.ToList();
customervm.States = states;
// Retrieve list of Citys
var citys = db.Citys.ToList();
customervm.Citys = citys;
// Retrieve list of Citys
var zips = db.Zips.ToList();
customervm.Zips = zips;
// Set the selected state
customervm.StateId = customer.StateId;
// Set the selected city
customervm.CityId = customer.CityId;
// Set the selected zip
customervm.ZipId = customer.ZipId;
}
return View(customervm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CustomerFormVM vmEdit)
{
if (ModelState.IsValid)
{
Customer customer = db.Customers.SingleOrDefault(c => c.CustomerId == vmEdit.CustomerId);
if (customer == null)
{
return NotFound();
}
customer.FirstName = vmEdit.FirstName;
customer.LastName = vmEdit.LastName;
customer.StateId = vmEdit.StateId;
customer.CityId = vmEdit.CityId;
customer.ZipId = vmEdit.ZipId;
db.Entry(customer).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vmEdit);
}
}
Create View
<div class="form-group">
#Html.LabelFor(c => c.FirstName)
#Html.TextBoxFor(c => c.FirstName, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(c => c.LastName)
#Html.TextBoxFor(c => c.LastName, new { #class = "form-control" })
</div>
<div class="form-group">
#*#Html.LabelFor(s => s.StateId)
#Html.DropDownListFor(s => s.StateId, new SelectList(Model.States, "StateId", "Abbr"), "", new { #class = "form-control" })
#Html.ValidationMessageFor(s => s.StateId)*#
<label asp-for="StateId "></label>
<select asp-for="StateId " asp-items="Model.States" class="form-control" id="state-target"></select>
<span asp-validation-for="StateId " class="text-danger"></span>
</div>
<div class="form-group">
#*#Html.LabelFor(ct => ct.CityId)
#Html.DropDownListFor(ct => ct.CityId, new SelectList(Model.Citys, "CityId", "Name"), "", new { #class = "form-control" })
#Html.ValidationMessageFor(ct => ct.CityId)*#
<label asp-for="CityId"></label>
<select asp-for="CityId" asp-items="Model.Citys" class="form-control" id="city-target"></select>
<span asp-validation-for="CityId" class="text-danger"></span>
</div>
<div class="form-group">
#Html.LabelFor(z => z.ZipId)
#Html.DropDownListFor(z => z.ZipId, new SelectList(Model.Zips, "ZipId", "PostalCode"), "", new { #class = "form-control" })
#Html.ValidationMessageFor(z => z.ZipId)
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
}
#section scripts {
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
<script src="~/lib/js/example.js"></script>,
}
I had a similar situation but in my example I have a Root folder and depending on which root folder I am using the next drop down list would display the corresponding sub-folders.
Not sure if there is a purly asp.net solution but, I used Jquery/Ajax for this.
Your code should look something like this:
html list:
<label asp-for="StateId "></label>
<select asp-for="StateId " asp-items="Model.States" class="form-control" id="state-target"></select>
<span asp-validation-for="StateId " class="text-danger"></span>
<label asp-for="CityId"></label>
<select asp-for="CityId" asp-items="Model.Citys" class="form-control" id="city-target"></select>
<span asp-validation-for="CityId" class="text-danger"></span>
Jquery code, you write this in .js file and then add it to a specific view with this statement<script src="~/js/example.js"></script>, Don't forget you need to add a jquery library to your project before any other javascript, and your example.js will contain:
$(document).ready(function () {
$("#state-target").on("change", function () {
$list = $("#city-target");
$.ajax({
url: "/getCities",
type: "GET",
data: { id: $("#state-target").val() }, //id of the state which is used to extract cities
traditional: true,
success: function (result) {
$list.empty();
$.each(result, function (i, item) {
$list.append('<option value="' + item["CityId"] + '"> ' + item["Name"] + ' </option>');
});
},
error: function () {
alert("Something went wrong call the police");
}
});
});
});
The Ajax request will call this action in the Controller which will retrieve a list of cities from the database (using something like return dbContext.CityTable.Where(c => c.StateId == id).ToList() inside a getCititesFromDatabaseByStateId(id) method) and then return the Json object, the success function will create a list of options and apply it:
public IActionResult getCities(int id)
{
var cities = new List<City>();
cities = getCititesFromDatabaseByStateId(id); //call repository
return Json(citites);
}
In your ViewModel consider changing IEnumerable<State/City/Zip> (IEnumerable<T>) to IEnumerable<SelectListItem>. I can say as well your Model's are messy (but if you can get data the from the database focus on getting the list working 1st), consider improving them later.
Fix for 2 errors mentioned in the comments:
public List<City> getCititesFromDatabaseByStateId(int id)
{
return db.Citys.Where(c => c.StateId == id).ToList();
}
public ActionResult Create()
{
var states = new SelectList(db.States.ToList(), "StateId", "Abbr");
var citys = new SelectList(db.Citys.ToList(), "CityId", "Name");
var zips = new SelectList(db.Zips.ToList(), "ZipId", "Code");
var viewModel = new CustomerFormVM
{
States = states,
Citys = citys,
Zips = zips
};
return View(viewModel);
}
When I try to create a ticket on my create.cshtml it gives me this error. I think it's because my Category uses a dropdownlist using ViewBags while my User and Administrator dropdown list doesn't.
The INSERT statement conflicted with the FOREIGN KEY constraint
"FK_dbo.Ticket_dbo.Category_CategoryID". The conflict occurred in
database "RecreationalServicesTicketingSystem.DAL.IssueContext", table
"dbo.Category", column 'CategoryID'. The statement has been
terminated.
TicketController.cs
public class TicketController : Controller
{
private IssueContext db = new IssueContext();
public ActionResult Create()
{
TicketVM model = new TicketVM();
ConfigureViewModel(model);
ViewBag.CategoryID = new SelectList(db.Categories, "CategoryID", "CategoryName");
ViewBag.AllUsers = db.Users.ToList().Select(u => new SelectListItem() { Value = u.UserID.ToString(), Text = string.Format("{0} {1}", u.FirstMidName, u.LastName) });
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(TicketVM model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
Ticket ticket = new Ticket
{
Issue = model.Issue,
IssuedTo = model.IssuedTo
};
if (ModelState.IsValid)
{
db.Tickets.Add(ticket);
ERROR------> db.SaveChanges(); <------ ERROR
return View();
}
ViewBag.CategoryID = new SelectList(db.Categories, "CategoryID", "CategoryName", ticket.CategoryID);
ViewBag.AllUsers = db.Users.ToList().Select(u => new SelectListItem() { Value = u.UserID.ToString(), Text = string.Format("{0} {1}", u.FirstMidName, u.LastName) });
ViewBag.AllAdmins = db.Users.Where(u => u.IsAdministrator).Include(u => u.Tickets);
return View(ticket);
}
private void ConfigureViewModel(TicketVM model)
{
IEnumerable<User> admins = db.Users.Where(u => u.IsAdministrator).OrderBy(u => u.LastName);
model.AdministratorList = admins.Select(a => new SelectListItem
{
Value = a.UserID.ToString(),
Text = string.Format("{0} {1}", a.FirstMidName, a.LastName)
});
}
}
\Views\Ticket\Create.cshtml
#model RecreationalServicesTicketingSystem.ViewModels.TicketVM
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Ticket</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CategoryID, "Category")
</div>
<div class="editor-field">
#Html.DropDownList("CategoryID", String.Empty)
#Html.ValidationMessageFor(model => model.CategoryID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.UserID, "User")
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.UserID, (IEnumerable<SelectListItem>)ViewBag.AllUsers, "Please select")`
#Html.ValidationMessageFor(model => model.UserID)
</div>
<div class="editor-field">
#using (Html.BeginForm())
{
#Html.HiddenFor(m => m.UserID)
<div class="form-group">
#Html.LabelFor(m => m.IssuedTo)
#Html.DropDownListFor(m => m.IssuedTo, Model.AdministratorList, "Please select", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.IssuedTo)
</div>
<div class="form-group">
#Html.LabelFor(m => m.Issue)
#Html.TextBoxFor(m => m.Issue, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Issue)
</div>
}
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Category.cs
public class Category
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; }
}
Ticket.cs
public enum Priority
{
Low, Med, High
}
public class Ticket
{
public int? TicketID { get; set; }
[Required(ErrorMessage = "Please enter the description")]
public string Issue { get; set; }
[Display(Name = "Administrator")]
[Required(ErrorMessage = "Please select the Administrator")]
public int IssuedTo { get; set; }
public int Author { get; set; }
[DisplayFormat(NullDisplayText = "No Priority")]
public Priority? Priority { get; set; }
[ForeignKey("CategoryID")]
public virtual Category Category { get; set; }
public int CategoryID { get; set; }
public int UserID { get; set; }
[ForeignKey("UserID")]
public virtual User User { get; set; }
}
ViewModels\TicketVM.cs
public class TicketVM
{
public int? UserID { get; set; }
[Required(ErrorMessage = "Please enter the description")]
public string Issue { get; set; }
[Display(Name = "Administrator")]
[Required(ErrorMessage = "Please select the Administrator")]
public int IssuedTo { get; set; }
public IEnumerable<SelectListItem> AdministratorList { get; set; }
public int CategoryID { get; set; }
}
AccountController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using DotNetOpenAuth.AspNet;
using Microsoft.Web.WebPages.OAuth;
using WebMatrix.WebData;
using RecreationalServicesTicketingSystem.Filters;
using RecreationalServicesTicketingSystem.Models;
namespace RecreationalServicesTicketingSystem.Controllers
{
[Authorize]
[InitializeSimpleMembership]
public class AccountController : Controller
{
//
// GET: /Account/Login
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
{
return RedirectToLocal(returnUrl);
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
//
// POST: /Account/LogOff
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
WebSecurity.Logout();
return RedirectToAction("Index", "Home");
}
//
// GET: /Account/Register
[AllowAnonymous]
public ActionResult Register()
{
return View();
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
WebSecurity.Login(model.UserName, model.Password);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
//
// POST: /Account/Disassociate
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Disassociate(string provider, string providerUserId)
{
string ownerAccount = OAuthWebSecurity.GetUserName(provider, providerUserId);
ManageMessageId? message = null;
// Only disassociate the account if the currently logged in user is the owner
if (ownerAccount == User.Identity.Name)
{
// Use a transaction to prevent the user from deleting their last login credential
using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.Serializable }))
{
bool hasLocalAccount = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
if (hasLocalAccount || OAuthWebSecurity.GetAccountsFromUserName(User.Identity.Name).Count > 1)
{
OAuthWebSecurity.DeleteAccount(provider, providerUserId);
scope.Complete();
message = ManageMessageId.RemoveLoginSuccess;
}
}
}
return RedirectToAction("Manage", new { Message = message });
}
//
// GET: /Account/Manage
public ActionResult Manage(ManageMessageId? message)
{
ViewBag.StatusMessage =
message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
: message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
: "";
ViewBag.HasLocalPassword = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
ViewBag.ReturnUrl = Url.Action("Manage");
return View();
}
//
// POST: /Account/Manage
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Manage(LocalPasswordModel model)
{
bool hasLocalAccount = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
ViewBag.HasLocalPassword = hasLocalAccount;
ViewBag.ReturnUrl = Url.Action("Manage");
if (hasLocalAccount)
{
if (ModelState.IsValid)
{
// ChangePassword will throw an exception rather than return false in certain failure scenarios.
bool changePasswordSucceeded;
try
{
changePasswordSucceeded = WebSecurity.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword);
}
catch (Exception)
{
changePasswordSucceeded = false;
}
if (changePasswordSucceeded)
{
return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
}
else
{
ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
}
}
}
else
{
// User does not have a local password so remove any validation errors caused by a missing
// OldPassword field
ModelState state = ModelState["OldPassword"];
if (state != null)
{
state.Errors.Clear();
}
if (ModelState.IsValid)
{
try
{
WebSecurity.CreateAccount(User.Identity.Name, model.NewPassword);
return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
}
catch (Exception)
{
ModelState.AddModelError("", String.Format("Unable to create local account. An account with the name \"{0}\" may already exist.", User.Identity.Name));
}
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
//
// POST: /Account/ExternalLogin
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
return new ExternalLoginResult(provider, Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
}
//
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
if (!result.IsSuccessful)
{
return RedirectToAction("ExternalLoginFailure");
}
if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
{
return RedirectToLocal(returnUrl);
}
if (User.Identity.IsAuthenticated)
{
// If the current user is logged in add the new account
OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name);
return RedirectToLocal(returnUrl);
}
else
{
// User is new, ask for their desired membership name
string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId);
ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
ViewBag.ReturnUrl = returnUrl;
return View("ExternalLoginConfirmation", new RegisterExternalLoginModel { UserName = result.UserName, ExternalLoginData = loginData });
}
}
//
// POST: /Account/ExternalLoginConfirmation
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl)
{
string provider = null;
string providerUserId = null;
if (User.Identity.IsAuthenticated || !OAuthWebSecurity.TryDeserializeProviderUserId(model.ExternalLoginData, out provider, out providerUserId))
{
return RedirectToAction("Manage");
}
if (ModelState.IsValid)
{
// Insert a new user into the database
using (UsersContext db = new UsersContext())
{
UserProfile user = db.UserProfiles.FirstOrDefault(u => u.UserName.ToLower() == model.UserName.ToLower());
// Check if user already exists
if (user == null)
{
// Insert name into the profile table
db.UserProfiles.Add(new UserProfile { UserName = model.UserName });
db.SaveChanges();
OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("UserName", "User name already exists. Please enter a different user name.");
}
}
}
ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(provider).DisplayName;
ViewBag.ReturnUrl = returnUrl;
return View(model);
}
//
// GET: /Account/ExternalLoginFailure
[AllowAnonymous]
public ActionResult ExternalLoginFailure()
{
return View();
}
[AllowAnonymous]
[ChildActionOnly]
public ActionResult ExternalLoginsList(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return PartialView("_ExternalLoginsListPartial", OAuthWebSecurity.RegisteredClientData);
}
[ChildActionOnly]
public ActionResult RemoveExternalLogins()
{
ICollection<OAuthAccount> accounts = OAuthWebSecurity.GetAccountsFromUserName(User.Identity.Name);
List<ExternalLogin> externalLogins = new List<ExternalLogin>();
foreach (OAuthAccount account in accounts)
{
AuthenticationClientData clientData = OAuthWebSecurity.GetOAuthClientData(account.Provider);
externalLogins.Add(new ExternalLogin
{
Provider = account.Provider,
ProviderDisplayName = clientData.DisplayName,
ProviderUserId = account.ProviderUserId,
});
}
ViewBag.ShowRemoveButton = externalLogins.Count > 1 || OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
return PartialView("_RemoveExternalLoginsPartial", externalLogins);
}
#region Helpers
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
public enum ManageMessageId
{
ChangePasswordSuccess,
SetPasswordSuccess,
RemoveLoginSuccess,
}
internal class ExternalLoginResult : ActionResult
{
public ExternalLoginResult(string provider, string returnUrl)
{
Provider = provider;
ReturnUrl = returnUrl;
}
public string Provider { get; private set; }
public string ReturnUrl { get; private set; }
public override void ExecuteResult(ControllerContext context)
{
OAuthWebSecurity.RequestAuthentication(Provider, ReturnUrl);
}
}
private static string ErrorCodeToString(MembershipCreateStatus createStatus)
{
// See http://go.microsoft.com/fwlink/?LinkID=177550 for
// a full list of status codes.
switch (createStatus)
{
case MembershipCreateStatus.DuplicateUserName:
return "User name already exists. Please enter a different user name.";
case MembershipCreateStatus.DuplicateEmail:
return "A user name for that e-mail address already exists. Please enter a different e-mail address.";
case MembershipCreateStatus.InvalidPassword:
return "The password provided is invalid. Please enter a valid password value.";
case MembershipCreateStatus.InvalidEmail:
return "The e-mail address provided is invalid. Please check the value and try again.";
case MembershipCreateStatus.InvalidAnswer:
return "The password retrieval answer provided is invalid. Please check the value and try again.";
case MembershipCreateStatus.InvalidQuestion:
return "The password retrieval question provided is invalid. Please check the value and try again.";
case MembershipCreateStatus.InvalidUserName:
return "The user name provided is invalid. Please check the value and try again.";
case MembershipCreateStatus.ProviderError:
return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
case MembershipCreateStatus.UserRejected:
return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
default:
return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
}
}
#endregion
}
}
Models\AccountModels.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Globalization;
using System.Web.Security;
namespace RecreationalServicesTicketingSystem.Models
{
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
public class RegisterExternalLoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
public string ExternalLoginData { get; set; }
}
public class LocalPasswordModel
{
[Required]
[DataType(DataType.Password)]
[Display(Name = "Current password")]
public string OldPassword { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "New password")]
public string NewPassword { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm new password")]
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
public class LoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
public class ExternalLogin
{
public string Provider { get; set; }
public string ProviderDisplayName { get; set; }
public string ProviderUserId { get; set; }
}
}
Im new to MVC and I had this problem, please help me,
when I try to upload an image to my website project ,this error come up
"There is no ViewData item of type 'IEnumerable' that has the key 'TagId'."
this is my view model:
#model ImageSharingWithAuth.Models.ImageView
#{
ViewBag.Title = "Upload an Image";
}
<h2>#ViewBag.Title </h2>
#{Html.BeginForm("Upload", "Images", FormMethod.Post, new {enctype ="multipart/form-data"});}
<fieldset>
<legend >
Enter Image Information
</legend>
#Html.AntiForgeryToken()
<p>
Caption: #Html.TextBoxFor(model=>model.Caption)
#Html.ValidationMessage("Caption")
</p>
<p>
Select a tag : #Html.DropDownListFor(model=>model.TagId , ViewBag.Tags as SelectList)
</p>
<p>
Description :<br />
#Html.TextAreaFor(model=> model.Description,5,40,null)
#Html.ValidationMessage("Description")
</p>
<p>
Date taken: #Html.TextBoxFor(model=>model.DateTaken)
#Html.ValidationMessage("DateTaken")
</p>
<p>
<input type="file" name="ImageFile" />
</p>
<p>
<input type="submit" value="Upload" />
</p>
</fieldset>
<p>#ViewBag.Message</p>
<p> #Html.ValidationSummary() </p>
#{Html.EndForm(); }
this is the get and set for uploading:
private ImageSharingDB db = new ImageSharingDB();
[HttpGet]
public ActionResult Upload()
{
CheckAda();
//string userid = GetLoggedInUser();
//if (userid == null) {
// return ForceLogin();
//}
//else
{
ViewBag.Message = "";
//IEnumerable<Tag> tags = db.Tags;
ViewBag.Tags = new SelectList(db.Tags, "Id", "Name",1);
return View();
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload(ImageView image, HttpPostedFileBase ImageFile)
{
CheckAda();
TryUpdateModel(image);
if (ModelState.IsValid)
{
String userid = GetLoggedInUser();
//if (userid != null)
//{
// return ForceLogin();
//}
//else
User user = db.Users.SingleOrDefault(u => u.Userid.Equals(userid));
if (user != null)
{
// save image info on the db
Image imageEntity = new Image();
imageEntity.Id = image.Id;
imageEntity.Caption = image.Caption;
imageEntity.Description = image.Description;
imageEntity.DateTaken = image.DateTaken;
imageEntity.Approved = false;
imageEntity.User = user;
imageEntity.TagId = image.TagId;
if (ImageFile != null && ImageFile.ContentLength > 0)
{
db.Images.Add(imageEntity);
db.SaveChanges();
String imgFileName = Server.MapPath("~/Content/Images/img-"+imageEntity.Id+".jpg");
ImageFile.SaveAs(imgFileName);
return View("Details", image);
//return RedirectToAction("Details", imageEntity.Id);
}
else
{
ViewBag.Message = "No such image file specified";
return View();
}
}
else
{
ViewBag.Message = "No Scuh userid registered";
return View();
}
}
else
{
ViewBag.Message = "Please crrect the errorsin the form!";
return View();
}
}
this the model for ImageView :
namespace ImageSharingWithAuth.Models
{
public class ImageView
{
[Required]
[StringLength(40)]
public String Caption { get; set; }
[Required]
public int TagId { get; set; }
[Required]
[StringLength(200)]
public String Description { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:d}",ApplyFormatInEditMode=true)]
public DateTime DateTaken { get; set; }
[ScaffoldColumn(false)]
public int Id;
[ScaffoldColumn(false)]
public String Userid { get; set; }
[ScaffoldColumn(false)]
public String TagName { get; set; }
}
}
and the model for Image:
namespace ImageSharingWithAuth.Models
{
public class Image
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int Id {get;set;}
[MaxLength(40)]
public virtual string Caption { get; set; }
[MaxLength(200)]
public virtual string Description { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:d}")]
public virtual DateTime DateTaken { get; set; }
public virtual bool Approved { get; set; }
[ForeignKey("User")]
public virtual int UserId { get; set; }
public virtual User User { get; set; }
[ForeignKey("Tag")]
public virtual int TagId { get; set; }
public virtual Tag Tag { get; set; }
public Image() {
Approved = false;
}
}
}
try this in else block in httpPost method of controller
else
{
ViewBag.Message = "Please crrect the errorsin the form!";
ViewBag.Tags = new SelectList(db.Tags, "Id", "Name",1);
return View();
}