Double Edit ActionResult with [AllowAnonymous] and [Authorize] - asp.net-mvc

I have this problem: I can not create a double "Edit" ActionResult into a controller where my goal is to allow an anonymous user to change a number of fields through a filter that returns only one record in the output .... The system returns this error, and I knew, somehow, that the problem is related to the primary key.
CONTROLLER
// GET:
[Authorize]
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
MyTable mytable = await db.MyTable.FindAsync(id);
if (mytable == null)
{
return HttpNotFound();
}
return View(mytable);
}
[AllowAnonymous]
[HttpGet]
public async Task<ActionResult> EditAnonymus(int? fk_field1, string guid)
{
if (fk_field1 == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var query = (from i in db.MyTable
where i.Guid == guid && i.Fk_Field1==fk_Field1
select new { i.Id }).SingleOrDefault();
MyTable mytable = await db.MyTable.FindAsync(query.Id);
if (mytable == null)
{
return HttpNotFound();
}
return View(mytable);
}
// POST:
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "Id,Fk_table1,......")] MyTable mytable)
{
if (ModelState.IsValid)
{
try
{
db.Entry(mytable).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
catch (DbUpdateConcurrencyException ex)
{
Trace.Write(ex.Message);
}
}
return View(mytable);
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> EditAnonymus([Bind(Include = "Id,........")] MyTable mytable)
{
if (ModelState.IsValid)
{
try
{
db.Entry(mytable).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
catch (DbUpdateConcurrencyException ex)
{
Trace.Write(ex.Message);
}
}
return View(mytable);
}
VIEW (command for entry from another View)
#Html.ActionLink("Modify Anonymus",
"EditAnonumus", controllerName: "NameController",
routeValues: new
{ fk_table1 = Model.Id, guid = Request.QueryString["guid"] },
htmlAttributes: null)
VIEW (Edit)
#model ManagingEvent.Models.MyTable
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Anonymus Edit</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
//omiss
<div class="form-group">
#Html.LabelFor(model => model.Cognome, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Field, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Field, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
ERROR OUTPUT (after save)
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since
entities were loaded. See
http://go.microsoft.com/fwlink/?LinkId=472540 for information on
understanding and handling optimistic concurrency exceptions.The
thread 0x518 has exited with code 0 (0x0).

I think your problem is not related to the primary key but can be this line of code in the EditAnonymus method:
db.Entry(mytable).State = EntityState.Modified;
What you are doing is mark explicitly the entity as modified, EF will try to update it when you call SaveChangesAsync() and will expect to get the count of the rows updated (1), but if no properties have changed it will get 0 (no rows have been updated), therefore it will throw the exception.
I would comment that row and try to do a simple fetch-edit-save and see what happens.

Thanks to the user449689 guidance, I searched in internet and I have found this method works:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> EditAnonymus (int? Id)
{
if (Id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var TableToUpdate = await db.myTable.FindAsync(Id);
if (TryUpdateModel(TableToUpdate, "",
new string[] { "Field1","Field2","....","....","Field x" }))
{
try
{
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DataException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
}

Related

how to fix EntityValidationErrors

I want to update user but whene I click on submit I get this error : EntityValidationErrors in this ligne :
Ligne 335 : context.SaveChanges();
I am using Entity Framework in ASP.NET MVC project:
this this my edit action in controller :
// GET: ApplicationUsers/Edit/2 :
[AuthLog(Roles = "Super Administrateur")]
public ActionResult Edit(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
ApplicationUser user = context.Users.Find(id);
if (user == null)
{
return HttpNotFound();
}
return View(user);
}
// POST: ApplicationUsers/Edit/2
[AuthLog(Roles = "Super Administrateur")]
[HttpPost, ValidateInput(false), ActionName("Edit")]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,No_,RaisonSociale,Magasin,RemiseHabituelle,FamilyName,FirstName,EmailSup,Login,AffPrix,PasserCmd,EmailRespMagasin,Admin,BoursePR,Actif,IdSession,VendeurItirénant,ChargeClient,ValidOuAnnul,Email,EmailConfirmed,PasswordHash,SecurityStamp,PhoneNumber,PhoneNumberConfirmed,TwoFactorEnabled,LockoutEndDateUtc,LockoutEnabled,AccessFailedCount,UserName")] ApplicationUser applicationUser)
{
if (ModelState.IsValid)
{
context.Entry(applicationUser).State = EntityState.Modified;
context.SaveChanges();
return RedirectToAction("ListUsers","Account");
}
return View(applicationUser);
}
this is the Edit View :
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
<div class="form-group">
#Html.LabelFor(model => model.Login, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Login, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Login, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Enregistrer" class="btn btn-default" />
</div>
</div>
</div>
}
The solution was : that UserName attributes is required.I find this error by adding block try {} catch {} to my edit action :
public ActionResult Edit([Bind(Include = "Id,No_,RaisonSociale,Magasin,RemiseHabituelle,FamilyName,FirstName,EmailSup,Login,AffPrix,PasserCmd,EmailRespMagasin,Admin,BoursePR,Actif,IdSession,VendeurItirénant,ChargeClient,ValidOuAnnul,Email,EmailConfirmed,PasswordHash,SecurityStamp,PhoneNumber,PhoneNumberConfirmed,TwoFactorEnabled,LockoutEndDateUtc,LockoutEnabled,AccessFailedCount,UserName")] ApplicationUser applicationUser)
{
if (ModelState.IsValid)
{
context.Entry(applicationUser).State = EntityState.Modified;
try
{
context.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
Exception raise = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{ string message = string.Format("{0}:{1}",
validationErrors.Entry.Entity.ToString(),
validationError.ErrorMessage);
// raise a new exception nesting
// the current instance as InnerException
raise = new InvalidOperationException(message, raise);
}
}
throw raise;
}
return RedirectToAction("ListUsers","Account");
}
return View(applicationUser);
}

ASP.NET form field already have data

I have 2 methods(actions) to create new "racun". Difference is, 1st one has dropdown list to choos kupac_id(FK),and the 2nd already has kupac_id sent by GET method. First one looks like this:
// GET: racuns/Create
public ActionResult Create()
{
ViewBag.kupac_id = new SelectList(db.kupacs, "id_kupac", "naziv");
return View();
}
// POST: racuns/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id_racun,dv_racuna,status,dv_placanja,kupac_id")] racun racun)
{
if (ModelState.IsValid)
{
db.racuns.Add(racun);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.kupac_id = new SelectList(db.kupacs, "id_kupac", "naziv", racun.kupac_id);
return View(racun);
}
And the other one is like this:
// GET: racuns/CreateZaKupca
public ActionResult CreateZaKupca(int vid)
{
return View(new racun { kupac_id = vid });
}
// POST: racuns/CreateZaKupca
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateZaKupca([Bind(Include = "id_racun,dv_racuna,status,dv_placanja,kupac_id")] racun racun)
{
if (ModelState.IsValid)
{
db.racuns.Add(racun);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(racun);
}
So, when I run 1st action i got this -> http://prntscr.com/9k2cmc
And 2nd -> http://prntscr.com/9k2e56
Why is that, and can i get rid of those number and have empty field like in 1st action?
Ty for any help. EDIT:
<div class="form-group">
#Html.LabelFor(model => model.dv_racuna, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.dv_racuna, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.dv_racuna, "", new { #class = "text-danger" })
</div>
</div>
Part of code from view.
In your second action method, you are passing an object of your racun view model to the view and i am assuming that you have a property in this view model of type DateTime.
public class racun
{
public DateTime Datum_Racuna {set;get;}
}
And in your view, something like
#model racun
#using(Html.BeginForm())
{
#Html.EditorFor(s=>s.Datum_Racuna)
}
If you do not set the value of this property to a valid datetime, It will return you the DateTime.MinValue value(1/1/0001 12:00:00 AM), which is what you see in the form field.
If you wish to avoid this behaviour, you may change your property type from DateTime to Nullable DateTime(DateTime?).
public class racun
{
public DateTime? Datum_Racuna {set;get;}
}
Now since you changed the property type to nullable, you should do a null check before accessing the value to avoid Null Reference exceptions.
[HttpPost]
public ActionResult Create(racun model)
{
if(model.Datum_Racuna!=null)
{
var dtValue=model.Datum_Racuna.Value;
}
// to do :do something useful and return something useful.
}

How to add existing view with own controller as a partial view to another view?

i am using visual studio 2013 community edition.In my ASP.NET MVC application I had a view with model and controller as follows. I created the view from scafolding. It is database first approach. I added edmx file, then added controller with scafolding, which created views.
Model:
using System;
using System.Collections.Generic;
public partial class request
{
public request()
{
this.stocks = new HashSet<stock>();
this.transactions = new HashSet<transaction>();
}
public int request_id { get; set; }
public Nullable<long> request_no { get; set; }
public int request_status { get; set; }
public virtual ICollection<stock> stocks { get; set; }
public virtual ICollection<transaction> transactions { get; set; }
}
View:
#model MaterialManagement2.request
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>request</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.request_no, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.request_no, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.request_no, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.request_status, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.request_status, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.request_status, "", new { #class = "text-danger" })
</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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Controller:
namespace MaterialManagement2.Controllers
{
public class requestsController : Controller
{
private MaterialManagement2Entities db = new MaterialManagement2Entities();
// GET: requests
public ActionResult Index()
{
return View(db.requests.ToList());
}
// GET: requests/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
request request = db.requests.Find(id);
if (request == null)
{
return HttpNotFound();
}
return View(request);
}
// GET: requests/Create
public ActionResult Create()
{
return View();
}
// POST: requests/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "request_id,request_no,request_status")] request request)
{
if (ModelState.IsValid)
{
db.requests.Add(request);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(request);
}
// GET: requests/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
request request = db.requests.Find(id);
if (request == null)
{
return HttpNotFound();
}
return View(request);
}
// POST: requests/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "request_id,request_no,request_status")] request request)
{
if (ModelState.IsValid)
{
db.Entry(request).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(request);
}
// GET: requests/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
request request = db.requests.Find(id);
if (request == null)
{
return HttpNotFound();
}
return View(request);
}
// POST: requests/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
request request = db.requests.Find(id);
db.requests.Remove(request);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
Now i need this view to be rendered as partial view with another view who has separate controller and model. I have created another view(partial) with above mentioned model with create template. This partial view called "_request" resides in shared folder. Now i used
#Html.Partial("_request", new MaterialManagement2.request())
in my another view so i can use them both is single view but the create button of the new view with partial view does not work. How do i make that button work?
Below is a screen shot of the app. The view renders correctly and looks exactly like i wanted. The button does not works though.
You have to specify the first controller name in this line :
#using (Html.BeginForm("Create", "requestsController"))
and you should drop this in the submit button:
value="Create"

Asp.Net MVC 5, View not posting back to the controller

I am creating a simple login form using Asp.Net MVC 5. Everything is fine but when I click on submit button after giving User Id and Password, the view does not go back to the desired Controller Action (LogIn). Here is the Action:
[HttpPost]
public ActionResult LogIn(User user)
{
var auth_user = CheckAuthentication(user);
if(auth_user!=null)
{
Session["user"] = new User() { UserId = user.UserId, Name = user.Name };
return RedirectToAction("Index", "User");
}
return View();
}
[AllowAnonymous]
public ActionResult LogIn()
{
return View();
}
and the view:
#model FinancialManagement.Models.User
#{
ViewBag.Title = "LogIn";
}
<h2>LogIn</h2>
#using (Html.BeginForm("LogIn", "User", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>User</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.UserId, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UserId)
#Html.ValidationMessageFor(model => model.UserId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
</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>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
This is my complete User controller:
[Authorize]
public class UserController : Controller
{
private FinancialManagmentEntities db = new FinancialManagmentEntities();
// GET: /User/
public ActionResult Index()
{
return View(db.Users.ToList());
}
// GET: /User/Details/5
public ActionResult Details(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
User user = db.Users.Find(id);
if (user == null)
{
return HttpNotFound();
}
return View(user);
}
// GET: /User/Create
[AllowAnonymous]
public ActionResult Create()
{
return View();
}
// POST: /User/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(User user)
{
if (ModelState.IsValid)
{
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}
ActionResult LogOut()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
User CheckAuthentication(User user)
{
return db.Users.Where(u => u.UserId == user.UserId && u.Password == user.Password).FirstOrDefault();
}
[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
public ActionResult LogIn(User user)
{
var auth_user = CheckAuthentication(user);
if(auth_user!=null)
{
Session["user"] = new User() { UserId = user.UserId, Name = user.Name };
return RedirectToAction("Index", "User");
}
return View();
}
[AllowAnonymous]
public ActionResult LogIn()
{
return View();
}
public ActionResult Edit(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
User user = db.Users.Find(id);
if (user == null)
{
return HttpNotFound();
}
return View(user);
}
// POST: /User/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="UserId,Name,Password")] User user)
{
if (ModelState.IsValid)
{
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}
// GET: /User/Delete/5
public ActionResult Delete(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
User user = db.Users.Find(id);
if (user == null)
{
return HttpNotFound();
}
return View(user);
}
// POST: /User/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(string id)
{
User user = db.Users.Find(id);
db.Users.Remove(user);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
Try to specify the View's Name and your Model like that :
return View("NameOfView", YourModel);
If it doesn't work put the absolute path :
return View("~/Views/FolderName/ViewName.cshtml");

How to allow users to only edit their details in a catalog

I am starting on MVC 5 tutorial and implemented roles and users as followed by the link:
http://typecastexception.com/post/2013/11/11/Extending-Identity-Accounts-and-Implementing-Role-Based-Authentication-in-ASPNET-MVC-5.aspx
With Role based authentication in place, I now have an admin who can create users and also a catalog of companies listed under Catalog Controller. Only this user when logged in with his username and password set by the admin will be redirected to their company page they are representing to make the edits instead of the free control of editing everyone else's company.
How should I go about doing this?
This is my AccountController:
[Authorize]
public class AccountController : Controller
{
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
public UserManager<ApplicationUser> UserManager { get; private set; }
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
await SignInAsync(user, model.RememberMe);
}
//if (User.Identity.AuthenticationType == "CanEdit" )
//{
// return RedirectToAction()
//}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
[Authorize(Roles = "Admin")]
public ActionResult Register()
{
return View();
}
[HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = model.GetUser();
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
return RedirectToAction("Index", "Account");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
[Authorize(Roles = "Admin")]
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."
: message == ManageMessageId.Error ? "An error has occurred."
: "";
ViewBag.HasLocalPassword = HasPassword();
ViewBag.ReturnUrl = Url.Action("Manage");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public async Task<ActionResult> Manage(ManageUserViewModel model)
{
bool hasPassword = HasPassword();
ViewBag.HasLocalPassword = hasPassword;
ViewBag.ReturnUrl = Url.Action("Manage");
if (hasPassword)
{
if (ModelState.IsValid)
{
IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
if (result.Succeeded)
{
return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
}
else
{
AddErrors(result);
}
}
}
else
{
// User does not have a 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)
{
IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
if (result.Succeeded)
{
return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
}
else
{
AddErrors(result);
}
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
AuthenticationManager.SignOut();
return RedirectToAction("Index", "Home");
}
protected override void Dispose(bool disposing)
{
if (disposing && UserManager != null)
{
UserManager.Dispose();
UserManager = null;
}
base.Dispose(disposing);
}
[Authorize(Roles = "Admin")]
public ActionResult Index()
{
var Db = new ApplicationDbContext();
var users = Db.Users;
var model = new List<EditUserViewModel>();
foreach (var user in users)
{
var u = new EditUserViewModel(user);
model.Add(u);
}
return View(model);
}
[Authorize(Roles = "Admin")]
public ActionResult Edit(string id, ManageMessageId? Message = null)
{
var Db = new ApplicationDbContext();
var user = Db.Users.First(u => u.UserName ==id);
var model = new EditUserViewModel(user);
ViewBag.MessageId = Message;
return View(model);
}
[HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(EditUserViewModel model)
{
if (ModelState.IsValid)
{
var Db = new ApplicationDbContext();
var user = Db.Users.First(u => u.UserName == model.UserName);
user.FirstName = model.FirstName;
user.LastName = model.LastName;
user.Email = model.Email;
Db.Entry(user).State = System.Data.Entity.EntityState.Modified;
await Db.SaveChangesAsync();
return RedirectToAction("Index");
}
// If we got this far, something failed, redisplay form
return View(model);
}
[Authorize(Roles = "Admin")]
public ActionResult Delete(string id = null)
{
var Db = new ApplicationDbContext();
var user = Db.Users.First(u => u.UserName == id);
var model = new EditUserViewModel(user);
if (user == null)
{
return HttpNotFound();
}
return View(model);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult DeleteConfirmed(string id)
{
var Db = new ApplicationDbContext();
var user = Db.Users.First(u => u.UserName == id);
Db.Users.Remove(user);
Db.SaveChanges();
return RedirectToAction("Index");
}
[Authorize(Roles = "Admin")]
public ActionResult UserRoles(string id)
{
var Db = new ApplicationDbContext();
var user = Db.Users.First(u => u.UserName == id);
var model = new SelectUserRolesViewModel(user);
return View(model);
}
[HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public ActionResult UserRoles(SelectUserRolesViewModel model)
{
if (ModelState.IsValid)
{
var idManager = new IdentityManager();
var Db = new ApplicationDbContext();
var user = Db.Users.First(u => u.UserName == model.UserName);
idManager.ClearUserRoles(user.Id);
foreach (var role in model.Roles)
{
if (role.Selected)
{
idManager.AddUserToRole(user.Id, role.RoleName);
}
}
return RedirectToAction("index");
}
return View();
}
#region Helpers
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError("", error);
}
}
private bool HasPassword()
{
var user = UserManager.FindById(User.Identity.GetUserId());
if (user != null)
{
return user.PasswordHash != null;
}
return false;
}
public enum ManageMessageId
{
ChangePasswordSuccess,
SetPasswordSuccess,
RemoveLoginSuccess,
Error
}
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
#endregion
}
Edit View
Catalog Controller edit view:`#model Catalog.Models.Partner
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm("Edit", "Catalog", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.Company, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.Company, new { #class = "form-control", autocomplete = "off" })
#Html.ValidationMessageFor(model => model.Company)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Description, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.Description, new { #class = "form-control", autocomplete = "off" })
#Html.ValidationMessageFor(model => model.Description)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Details, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextAreaFor(model => model.Details, new { #class = "form-control", rows = 10 })
#Html.ValidationMessageFor(model => model.Details)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.InCharge, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.InCharge, new { #class = "form-control", autocomplete = "off" })
#Html.ValidationMessageFor(model => model.InCharge)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Email, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.Email, new { #class = "form-control", autocomplete = "off" })
#Html.ValidationMessageFor(model => model.Email)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Logo, new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="file" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<hr />
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
`
When grabbing the database context, add a Where() clause that will just grab the information the current user belongs to. if you add this as a namespace using Microsoft.AspNet.Identity; then you can utilize the User.Identity.GetUserId() to return the current user's id and use that in your Where() clause to view only what the user/partner can see.
Despite the date of the question I will leave my answer here because this question is relevant when you are developing a application and face the need to let only the logged user to see, edit or delete (or any other action) its own records.
The example is shown using the Entity Framework and ASP.NET Identity.
First of all you need to link your object model with the user. This is represented by the IdentityUser. Note that we are using the IdentityUser class because we are using ASP.NET Identity, otherwise we could use ClaimsIdentity.
public class UserObject
{
public int Id { get; set; }
public string Name { get; set; }
public IdentityUser User { get; set; }
}
After this point when you save a UserObject on your Context a field referencing the Id property of IdentityUser (the default name of the table for this class is AspNetUsers) will be created along with the UserObject table.
Then to get the current user you call HttpContext.GetOwinContext().Get<UserManager>() to get the UserManager after that you call UserManager.FindById(User.Idendity.GetUserId()). Just remember to get the IdentityDbContext associated with the Owin Context when inserting new objects otherwise a exception will be thrown.
public ActionResult Create(UserObjectViewModel uoViewModel)
{
UserObject uo = new UserObject();
// create the UserObject using the properties from the UserObjectViewModel
...
// get the User Manager
UserManager userManager = HttpContext.GetOwinContext().Get<UserManager>();
// assign the current User
uo.User = userManager.FindById(User.Identity.GetUserId())
...
}
From now on you can call User.Identity.GetUserId() to get the current User Id and send it along with your query parameters like this:
public ActionResult Get()
{
string currentUserId = User.Identity.GetUserId();
yourDbContext.Where(uo => uo.User.Id == currentUserId);
...
}

Resources