ASP.NET MVC5 not saving to the database - asp.net

I'd like to get a user from db by ID field, update one of the fields and save it.
I have a following action in my Users controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Update()
{
AspNetUser mister = db.AspNetUsers.Find(12);
mister.Permissions = 2;
db.Entry(mister).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("index", "users");
}
It is finding a right user, modifies the value on the mister object and calls save. Doesn't give any errors, but it is not saving?
Any help will be much appreciated.

Related

Getting the Object reference not set to an instance of an object exception in ASP.NET Core MVC

I'm trying to connect an object from one View to another. I have a user action history where I have all of my CRUD operations listed. I'm trying to add an action link that when I go to my action history the name of the object that was created/updated/deleted(soft delete), becomes a link that will redirect me to the Edit view of that object. I tried via. #Html.ActionLink like this:
#Html.ActionLink(item.PreduzvePibfkNavigation.NazivPreduzeca, "IzmenaPreduzeca","Preduzece", new {Id = item.PreduzvePibfk}, null)
This is my controller for the 'IzmenaPreduzeca' action:
[HttpGet]
public IActionResult IzmenaPreduzeca(int id)
{
Preduzece preduzece = _preduzece.getById(id);
ViewBag.izabrani = preduzece.NazivPreduzeca;
return View(preduzece);
}
[HttpPost]
public IActionResult IzmenaPreduzeca(Preduzece preduzece, IstorijaPromena istorijaPromena, string razlog)
{
try
{
_preduzece.Update(preduzece);
_preduzece.IstorijaPromene(preduzece, istorijaPromena, CrudType.Update, DateTime.Now, "Branislav Zivanovic", razlog);
_preduzece.SaveToDb();
return RedirectToAction("PregledPreduzeca");
}
catch (Exception ex)
{
return NotFound($"Error, details: {ex.Message}");
}
}
I don't understand why do I get this error
Object reference not set to an instance of an object
Is there another way?
This is the user action history:
Image of the user action history
input parameter id is always 0, fix the action header
[HttpGet("{id}")]
public IActionResult IzmenaPreduzeca(int id)

With same parameters and methods name, how can the controller finds which one to be invoked in ASP.NET core MVC

I am following the tutorial posted on the Microsoft website https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/details?view=aspnetcore-2.2
I just wonder once I click the delete button, how does it know which method or action should be invoked first? get or post? with the same parameters and action name
The code below might show you more details.
Thank you
// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.ID == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var movie = await _context.Movie.FindAsync(id);
_context.Movie.Remove(movie);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
As stated in the comments above, a GET request will usually return a View to perform an action, but it won't actually perform that action unless it is a POST request, e.g. a GET request to an action named Edit will grab the data to edit and display it. That's it. The changes are not saved to the database until a POST to the Edit action is submitted.
Overloaded methods are required to have different parameter signatures. Since the other scaffolded pairs of CRUD actions (except Delete) have different signatures, they can have the same name. But since both the GET and POST methods for the Delete action have the same parameter signature, one of them needs to be renamed, which is why the POST action is named DeleteConfirmed. However, having GET and POST methods named differently will break the routing built into MVC. Adding the ActionName("Delete") attribute fixes that.
Routing depend on the HTTP Method + The name + The Parameters
so, when you issue a GET request to /Movies/Delete/5 it will use the first one.
When you issue a POST request to /Movies/Delete/5, it will use the second one.
If you have more than one POST method with different parameters, it will use the most specific. ex:
Delete(int id, bool confirm)
Delete(int id)
If you issue a POST request to /Movies/Delete/5, it will go for the second action, but if you change it to /Movies/Delete/5?confirm=true, it will go for the first one unless the parameter confirm was nullable, in this case it will throw an exception as it will not be able to determine which action to invoke

Custom redirection in ASP.NET MVC 4

I'm trying to build a two-step custom registration for users in my ASP.NET MVC 4 application. This involves redirecting users after registration to the Edit view in the User Controller. I've tweaked the code in the stock Account Controller template to achieve this.
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("Edit", "User", new { id = WebSecurity.CurrentUserId });
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
return View(model);
}
However when I run this I get a 404 on the address bar it shows
http://localhost:17005/User/Edit/-1
Which means it's going into the Edit action of user controller, but then ending up with a Id of -1. Any help would be appreciated.
Membership.GetUser().ProviderUserKey
Alternatively you could not pass a user id to the edit action and have the code use the currently logged in user.
RedirectToAction("Edit", "User");
In your user controller
[Authorize]
public ActionResult Edit()
{
object userId = Membership.GetUser().ProviderUserKey;
}
Please excuse brevity as I am currently on my mobile

MVC Music Store Saving concurrency. What is causing this?

I am doing the MVC Music Store Tutorials and I have finished, every works fine but for some reason when I edit an album on an Admin account it comes up with this error when I try to save changes. It highlights db.SaveChanges(); what is causing this problem?
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
public ActionResult Edit(int id)
{
Album album = db.Albums.Find(id);
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);
return View(album);
}
//
// POST: /StoreManager/Edit/5
[HttpPost]
public ActionResult Edit(Album album)
{
if (ModelState.IsValid)
{
db.Entry(album).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);
return View(album);
}
I am the only person accessing the site I have made as I am doing it locally only on my machine, I have been told that somebody else may changed something but this is not the case. What's going on?
This issue is explained on this page on the musicstore codeplex site.
Here is an excerpt:
In the Album class, you've defined [Bind(Exclude = "AlbumId")] on the class, which means that the code won't try and bind the AlbumId from the form. Which is fine, except that on the edit page, you're passing in a populated Album, which is presumably being populated using binding, which is of course ignoring the Album Id, so the AlbumId of the object passed into the edit method, is always 0, which throws a misleading concurrency error, because no rows are affected, because there's no album with ID of 0.

RedirectToAction usage in asp.net mvc

I want to post some questions about ASP.Net MVC. I am not familiar with web developing, But I was assigned to the web part of a project. We are doing the following: first, we create get & set properties for the person data:
public class Person
{
public int personID {get;set;}
public string personName {get;set;}
public string nric {get;set;}
}
and after login, we put the data in a class Person object and we use RedirectToAction like this:
return RedirectToAction("profile","person",new { personID = Person.personID});
It's working normally, but the parameter are shown in the URL. How can I hide them and also
can I hide the action name? Guide me the right way with some examples, please.
The parameter are shown in the URL because that is what the third parameter to RedirectToAction is - the route values.
The default route is {controller}/{action}/{id}
So this code:
return RedirectToAction("profile","person",new { personID = Person.personID});
Will produce the following URL/route:
/Person/Profile/123
If you want a cleaner route, like this (for example):
/people/123
Create a new route:
routes.MapRoute("PersonCleanRoute",
"people/{id}",
new {controller = "Person", action = "Profile"});
And your URL should be clean, like the above.
Alternatively, you may not like to use ID at all, you can use some other unique identifier - like a nickname.
So the URL could be like this:
people/rpm1984
To do that, just change your route:
routes.MapRoute("PersonCleanRoute",
"people/{nickname}",
new {controller = "Person", action = "Profile"});
And your action method:
public ActionResult Profile(string nickname)
{
}
And your RedirectToAction code:
return RedirectToAction("profile","person",new { nickname = Person.nickname});
Is that what your after?
If you don't want the parameter to be shown in the address bar you will need to persist it somewhere on the server between the redirects. A good place to achieve this is TempData. Here's an example:
public ActionResult Index()
{
TempData["nickname"] = Person.nickname;
return RedirectToAction("profile", "person");
}
And now on the Profile action you are redirecting to fetch it from TempData:
public ActionResult Profile()
{
var nickname = TempData["nickname"] as string;
if (nickname == null)
{
// nickname was not found in TempData.
// this usually means that the user directly
// navigated to /person/profile without passing
// through the other action which would store
// the nickname in TempData
throw new HttpException(404);
}
return View();
}
Under the covers TempData uses Session for storage but it will be automatically evicted after the redirect, so the value could be used only once which is what you need: store, redirect, fetch.
this may be solution of problem when TempData gone after refresh the page :-
when first time you get TempData in action method set it in a ViewData & write check as below:
public ActionResult Index()
{
TempData["nickname"] = Person.nickname;
return RedirectToAction("profile", "person");
}
now on the Profile action :
public ActionResult Profile()
{
var nickname = TempData["nickname"] as string;
if(nickname !=null)
ViewData["nickname"]=nickname;
if (nickname == null && ViewData["nickname"]==null)
{
throw new HttpException(404);
}
else
{
if(nickname == null)
nickname=ViewData["nickname"];
}
return View();
}
Temp data is capable of handling single subsequent request. Hence, value gone after refresh the page. To mitigate this issue, we can use Session variable also in this case. Try below:
public ActionResult Index(Person _person)
{
Session["personNickName"] = _person.nickName;
return RedirectToAction("profile", "person");
}
And in "profile" actionmethod:
public ActionResult profile()
{
Person nickName=(Person)Session["personNickName"];
if(nickName !=null)
{
//Do the logic with the nickName
}
}

Resources