Within my Home controller is the Index() action. Within Index() I return the a user object from the database using the currently authenticated user's ID:
return View(db.Users.Find(User.UserId));
That works properly and the URL is simply:
https://localhost:44301/
However elsewhere in the Home controller in a separate action I modify the current user and pass it back into the index view using:
return RedirectToAction("Index", user);
When I do this the URL becomes cluttered with a serialized version of the User model:
https://localhost:44301/Home/Index/4?Name=katrina&Administrator=True&PasswordEncodedHash=1000%3AqzWR8U6poGKshxHDsP%2B5yFhz5AZ01%2Fv1%3ASqCG0SliIpjX0M0jjkQqAf5aunTVS2gx&Tests=System.Collections.Generic.List%601%5BLearningManagementSystem.Models.Test%5D&UserTestAttempts=System.Collections.Generic.List%601%5BLearningManagementSystem.Models.UserTestAttempt%5D&Phones=System.Collections.Generic.List%601%5BLearningManagementSystem.Models.Phone%5D
I imagine I doing something dumb with the way I am redirecting the action however I cannot figure out how to fix this. I have tried adding a custom route but the "?Name=...." still gets appended to that.
(Edit) Code from that other action:
public ActionResult ToggleAdministrator()
{
if (Request.IsAuthenticated)
{
var user = db.Users.Find(User.UserId);
user.Administrator = !user.Administrator;
db.SaveChanges();
Response.Cookies.Add(cookie);
return RedirectToAction("Index", user);
}
return RedirectToAction("Index", (User)null);
}
I think you don't need to pass whole data while redirecting to some action using RedirectToAction.
Suppose you have an action Index in Home controller.
Public ActionResult Index(int id)
{
-- write the code here to fetch data based on that id
-- like
var user = db.Users.FirstOrDefault(x=>x.Id = id);
return View(user);
}
Now for this you just need to use redirect to action like below:
return RedirectToAction("Index", new { Id= 5 });
Note:
Never pass a complex type object in QueryString or in GET requests
Related
I have an application in asp.net mvc
I have a controller named LoginController which has two action method
Index
loginCheck(Username, Password)
Both return ActionResult
Index action return view which has a login form.
//Code
public class LoginController : Controller
{
public ActionResult Index()
{
return view();
}
}
loginCheck action method is called using ajax call when a user click login button on login form.
WithIn loginCheck I'm checking username and password if it is correct I'm creating a session using
Session["User"] = Username And return RedirectToAction("Index", "Configuration");
//Here is code
public class LoginController : Controller
{
[HttpPost]
public ActionResult loginCheck(string UserName, string Password)
{
Getting user Id and password
Checking
If(correct)
Then
Session["User"] = Username;
return RefirectToAction("Index", "Cobfiguration");
Else
return RedirectToAction("Index");
}
}
After above line the control goes to Index action method of Configuration controller.
It checks session if exist then do stuff and return view of configuration action method Index with data in an object of Configuration model class, and if session doesnot exist then just return login index action which basically loads login form.
if (Session["User"] != null)
{
//do stuff
return view(modelObject);
}
else
{
return RedirectToAction("Index", "Login");
}
So the problem is controller is transferring to index method of configuration controller, code is executing everything and even return view(modelObject); but the view of configuration index is not showing. I don't understand why.
Anything anyone can tell?
When you are using AJAX to call the method, the whole process happens without reloading the page. Everything is executing as expected, but the page is not reloading. You need to either handle the redirect in the callback of your AJAX call, or just send the POST request synchronously.
So in the same controller I have a Login Action method like this:
public ActionResult Login()
{
LoginModel model = this.LoginManager.LoadLoginPageData();
this.ForgotPasswordMethod = model.ForgotPasswordMethod;
return View(model);
}
Notice I set a variable there: ForgotPasswordMethod
So now when there on that page if they click on a link, it call another action result in the same controller class like this:
public ActionResult ForgotPassword()
{
if (!string.IsNullOrWhiteSpace(this.ForgotPasswordMethod) && this.ForgotPasswordMethod.Trim().ToUpper() == "TASKS")
return View();
return null; //todo change later.
}
Notice I tried to read the value of ForgotPasswordMethod , but it was NULL but it is NOT null when I am in the Login() method. So what should I do?
ASP.NET MVC was designed to return back to a cleaner, more straightforward web world built on HTTP, which is stateless, meaning that there is no "memory" of what has previously occurred unless you specifically use a technique that ensures otherwise.
As a result, whatever state you set via one ActionResult will no longer be the same state that exists when another ActionResult is invoked.
How do you "fix" this? You have a variety of options, depending on what your needs are:
Render the value to the client and post the value back to your second ActionResult method.
Store the value as a header and check that header.
Store the value in a cookie and check the cookie.
Store the value in session.
Store the value in a database.
Store the value in a static dictionary.
what if you store forgotpasswordmethod in Viewbag like
public ActionResult Login()
{
LoginModel model = this.LoginManager.LoadLoginPageData();
Viewbag.ForgotPasswordMethod = model.ForgotPasswordMethod;
return View(model);
}
then in the link of your page you can pass the value from the ViewBag
<a href=#Url.Action("ForgotPassword", "Name of your Controller", new { methodName = ViewBag.ForgotPasswordMethod })>Forgot Password</a>
Change your forgotpassword to
public ActionResult ForgotPassword(string methodName)
{
if (!string.IsNullOrWhiteSpace(methodName) && methodName.Trim().ToUpper() == "TASKS")
return View();
return null; //todo change later.
}
Form posts from webpage MakeBooking to FinalBooking to ascertain certain information such as number of guests, so the FinalBooking page can give you enough textboxes to input guest information for all guests required.
When in debug mode, both models in MakeBooking post are populated. After post, in FinalBooking, model is null.
[HttpPost]
public ActionResult MakeBooking(BookingModel model)
{
return RedirectToAction("FinalBooking", "Booking", new { model = model });
}
public ActionResult FinalBooking(BookingModel model)
{
return View(model);
}
Any info would be appreciated.
It should work
return RedirectToAction("FinalBooking", "Booking", model);
You can not pass a model with RedirectToAction like that. you need to use either TempData or Session to transfer the model object between your calls.
RedirectToAction method returns an HTTP 302 response to the browser, which causes the browser to make a GET request to the specified action.
The below example shows how to transfer data using TempData.
[HttpPost]
public ActionResult MakeBooking(BookingModel model)
{
TempData["TempBookingModel"]=model;
return RedirectToAction("FinalBooking", "Booking");
}
public ActionResult FinalBooking()
{
var model= TempData["TempBookingModel"] as BookingModel;
return View(model);
}
Internally TempData is using Session as the storage mechanism.
I am fairly new to MVC and i'm looking for advice on how to setup a particular registration controller.
I have a controller called AccountController which has a Register method and I have a Register.cshtml.
Now, one of the biggest problems I seem stuck on is that I have 2 dropdowns that I need to populate based on the response from a service as these values change depending on location and other various parameters.
I have my page started and loading but I'm not sure what to do once a user click 'register'.
#model Adw.Models.RegisterModel //This is my model
#Html.DropDownListFor(m => m.States, new SelectList(Model.States)); // I load my dropdowns here
[AllowAnonymous]
public ActionResult Register(RegisterModel model)
{
model.States = Services.GetStates().Payload;
model.Countries = Services.GetCountries().Payload;
return View(model);
}
So my question is, when a user submits the form, should it come back to this same method? If so what would be the best way to validate that this is a submit rather than an initial load?
Also i haven't done much in the way of error handling and could use a suggestion on that, such as if either of the above service calls fail, then a registration cannot be completed, should that direct to a new page or is there a easy way to build that kind of error into the same page?
You should create two different method. One for GET and second for POST request:
[AllowAnonymous]
[HttpGet]
public ActionResult Register()
{
...
}
[AllowAnonymous]
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// create user
return this.RedirectToAction("SignIn");
}
else
{
return View(model);
}
}
You can review sample from default template.
So here's what I'd like to do. I have a page at /Admin/Vendors/Index. If a user is in a certain role and they go to this page, I want them to be redirected to another view that only shows them certain data.
Here's what I have:
public ActionResult Index()
{
if (User.IsInRole("Special User"))
{
SpecialIndex();
}
return View();
}
public ActionResult SpecialIndex()
{
var viewModel = GetSpecialData();
return View(viewModel);
}
So I thought that if the user was in the role and it calls the SpecialIndex method, it would call the method and send the user to the SpecialIndex view.
It does call the SpecialIndex method, but when I call return View(viewModel), it just goes back to the Index method, and the user is shown the Index view instead of SpecialIndex.
How can I fix that?
You should use the View() constructor that gets a view name in which case you can specifically say which view you want to return, or use the RedirectToAction method to redirect to the SpecialIndex action. See documentation public ActionResult Index()
{
if (User.IsInRole("Special User"))
{
return this.RedirectToAction("SpecialIndex");
}
return View();
}
Check User.IsInRole("Special User") it will solve your problem. Either way, you are returning a view for it.