register and login in one page changes my url - asp.net-mvc

Im having the following issue.
I have a View typed to a class SiteAuthenticationVM.cs.
The name of my view is "SiteAuthentication.cshtml" into the folder Views/Users
For other hand, i have one controller called UsersController with 4 actions:
[HttpGet]
public ActionResult Registration()
{
return View("SiteAuthentication");
}
[HttpPost]
public ActionResult Registration(SiteAuthenticationVM usertoregister)
{
return View("SiteAuthentication",usertoregister);
}
[HttpGet]
public ActionResult Login()
{
return View("SiteAuthentication");
}
[HttpPost]
public ActionResult Login(SiteAuthenticationVM usertologin)
{
return View("SiteAuthentication",usertoregister);
}
I have 2 routes defined:
"/register" is handled by UsersController Registration action.
"/login" is handled by UsersController Login action.
When i post my Login form is posted to /login if previously i was in url "/register", it changes to /login. Is there any way to keep my url "/register" for both post actions?
Is a bad practice if the url changes?

Your URL is denoting the controller method which is called, not whih View is being displayed. You can't change that, this is how MVC works. And your browser doesn't like to change its URL to 'B' if it needed 'A' to display that page, you cant really change it at rendertime.
Funny thing, if you had given your methods the same name, and had named your views differently, it would've worked without a hitch :-)
However, there are a few ways I can think of to get around this:
Give your methods the same name. This is the most straight-forward option. You can keep your View names, it's the method name that is important.
Make a method (e.g. "Switchboard") that calls either return View("Login") or return View("Register"). Your URL will contain "Switchboard" (you'll want a better name, but you get the idea).
Make the Login and Register pages into PartialViews. Display these in 1 View ("Switchboard", same name method). Then the URL will always denote the method ("Switchboard") you called for the View, not the PartialView.
Just remember, in MVC it's not about which View you are displaying, it's about which method you are calling.

Related

ASP.net MVC default route to show actual route

I have an MVC 3 app, my default route is app/index, which mean that if a user hits "http://www.something.com",
they are acutally seeing "http://www.something.com/app/".
However, I want to show the actual route always, which mean that when a user hits
"http://www.something.com", I want the url in address bar to be shown as "http://www.something.com/app/". How can I achieve this?
You can use an redirect in your action as follows:
public class HomeController : Controller
{
public ActionResult Index(){
return RedirectToAction("Index","App");
// or you can do a redirect to a URL. like 301.
return RedirectPermanent("/app");
}
}

How can I make an MVC POST return me to the previous page?

I have the following action which is called from a screen with a list of records.
[HttpPost]
//[Authorize(Roles = "admin")]
public ActionResult Edit(EditViewModel itemView)
{
Once the action has completed I would like to return to the page where the action was called from. However I don't want to refresh that page. I just want to go back to the populated screen using something similar to the "Previous" button in the browser. Right now when I click "save" my action does the following which is not what I want:
return RedirectToAction("Index");
Is there some way to Redirect to previous page with MVC3?
Something like the Stackoverflow functionality after I click edit to edit an answer where it returns to the post.
Instead of a redirection,
[HttpGet]
public ActionResult Index()
{
/// preform any processing necessary for your index page on GET
return View("Index");
}
[HttpPost]
public ActionResuit Edit(EditViewModel itemView)
{
if (ModelState.IsValid)
{
/// do whatever you want with your model...
}
// return the contents as they'd be rendered by the Index action
return Index();
}
Note that with this method the URL in the browser will still display the Edit url (like /area_name/edit), but you can fix that by:
Using a redirect (which you've said you don't want to do)
Using JavaScript to update the URL, or use history.back() as #AlanStephens suggested
Probably other methods that don't immediately come to mind.
However, I'd question whether this is really the best approach. Typically, users expect different URLs to do different things.
Or, if I understand you correctly and the edit action is being called from the Index page,
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost] /// from a form on Index
public ActionResult Index(EditViewModel model)
{
if (ModelState.IsValid)
{
////
}
return View();
}
and just take the /Edit out of play entirely. Again, I don't really care for this approach.
Based off the code you've given, it looks like you've got a paginated screen, with the ability to click edit on each row. Here's how I've solved this problem in the past.
On the Index page, when the page loads, whether it be from the main index or a paging method, add the following:
Session["CurrentUrl"] = Request.Url.ToString();
So now, at the end of the POST method for your edit page, do:
return Session["CurrentUrl"] == null ?
Index() :
Redirect(Session["CurrentUrl"]);
What you described is easily achieved using ajax calls. That way you perform whatever action you like and afterwards (on successful response), you can easily navigate from the current page, using javascript.
If you POST to a page and in response you return the same view you receive with a GET request (index page), then some users might hit F5 to reload that index page and get a warning in the browser, which actually says it will send the POST request again. This is pretty confusing for users and not really user friendly (not to mention numerous concerns related to idem-potency of it).
Although you don't like the redirect approach, because of the additional response, I guess, I should say that, in MVC, this is the correct way to do it, assuming you don't want to use ajax calls.

Show partial view based on parameter

In the process of updating a C# MVC 2.0 application!
I have a view “Signup” and another view “ForgotPassword”.
Each view have a with a submit button.
Each form is submitted to the same Controller but to two different ActionResult:
[HttpPost]
public ActionResult Signup(SignupModel signupModel)
{…}
[HttpPost]
public ActionResult ForgotPwd(ForgotPasswordModel forgotPasswordModel)
{…}
Upon completion my goal is to redirect the user to a “thankyou” page but based on where the user is coming from (either Signup or ForgotPassword) I wish to display a particular message (or a different UI).
Inside the same Controller, I created a “Thankyou” ActionResult:
public ViewResult Thankyou()
{
return View();
}
I was thinking of adding a parameter to my Thankyou() method which would allow me to know where the user is coming from (Signup or ForgotPwd). From there, make the “thankyou” page display the appropriate UI/message.
I’m looking for a clean and simple solution.
Should I create two View User Controls and show the appropriate one based on the parameter being passed?
In addition, instead of having an “ActionResult” for my Thankyou() method couldn’t I use a “PartialViewResult” ?
EDIT:
I was actually considering something along those lines…
Where ThankyouType is an Enum.
[HttpPost]
public ActionResult Signup(SignupModel signupModel)
{
//Validation code...
return View("Thankyou", ThankyouType.SignupDone);
}
[HttpPost]
public ActionResult ForgotPassword(ForgotPasswordModel forgotPasswordModel)
{
//Validation code...
return View("Thankyou", ThankyouType.ForgotPasswordDone);
}
And then have my “Thankyou” ViewResult like this:
public ViewResult Thankyou(ThankyouType type)
{
return View(type);
}
Doesn’t seem like I can create a strongly typed view based on Enum (unless I’m wrong).
Perhaps I’ll read more on PartialViewResults and/or find examples…but then again, I could be completely wrong.
I would personally give the ThankYou view a model that has the message you want to display, and have your two controller actions render the ThankYou view directly on success rather than calling a ThankYou action.
However, if you're sure you want a redirect, you may consider using the TempData collection to store a message or a key of some kind. The ThankYou controller can then retrieve this value and pass it to the View. This situation is what TempData was made for.
Edit
There's no reason you shouldn't be able to use an enum value as your model type, but if that gives you trouble you should at least be able to create a model type that has an enum property on it.
The strategy of sending the ThankYouType as part of the redirect request would work just fine, if that's what you prefer. The only potential downside is that it would look like this in the URL:
http://domain.com/controller/ThankYou?type=ForgotPasswordDone
I have no real arguments against it. There are lots of options. Use the one that feels best to you.

How to have POST ActionHandler return the GET ActionHandler by a custom Attribute?

Our system is MVC2 authenticated by ADFS 2. So when a user clicks on a bookmark for http://www.foo.com/Car/Details/3, this hits our Car controller and calls our Details GET action handler and passes 3 in as the ID (all basic MVC stuff). So we have this ActionHandler decorated with a [Authorize] attribute and have ADFS2 hooked up, so the page then redirects to our auth server which then redirects back to our app, but with a POST (all basic ADFS stuff). The problem is that this redirect is a POST and therefore our Details POST handler is called, but clearly it doesn't have the data I need.
Now I have identified some code that detects this scenario and this code looks something like this:
[Authorize]
[MySpecialHttpGet]
public ActionResult Details(long id)
{
var model = GetModel(id);
return View(model);
}
[Authorize]
[MySpecialHttpPost]
public ActionResult Details(long id, ViewModel model)
{
/***START OF SPECIAL CODE***/
// If we were posted to by ADFS, redirect to the GET handler.
if (Request.Form["wa"] != null && Request.Form["wa"].ToLower().Contains("signin"))
{
// We were posted to here but need to respond with the GET view.
return Redirect(Request.Url.AbsoluteUri);
}
/***END OF SPECIAL CODE***/
var result = Something.SaveData(model);
return result.ActionResultToReturnWith;
}
The problem with this is that I need to do this on every single POST ActionHandler in the app and I really don't want to do that. Given that I already have custom attributes on all of these ActionHandlers, I would like to use those attributes to inject this functionality for me.
Now the MySpecialHttpGet and MySpecialHttpPost are nothing incredibly special that you really need to know about other than they extend ActionMethodSelectorAttribute. I would LIKE to add code in the MySpecialPost attribute to inject that functionality.
So my question:
How would I add code to perform this kind of check in this Attribute?
For now, we have not found the solution we wanted and are simply pasting that code (well, a function call with that code in it) at the beginning of EVERY controller.

ASP.NET MVC - Go to a different view without changing URL

is it possible to go to a different View without changing the URL? For example in my Index View, I have a link to go the the Details View but I would like to keep the URL the same.
Thank you very much,
Kenny.
As already mentioned, you could make the Details link an Ajax.ActionLink and use this to change the content of a div.
Failing that, the only other way I can think of doing it is by making your details link a button and POST to your index action. You could apply CSS to the button to make it appear more like a normal html link.
public class HomeController : Controller {
public ActionResult Index() {
return View("Index");
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(int hiddenInputFieldId) {
return View("Details");
}
}
EDIT:
Based on JonoW's comment, you'll have to pass in a 'fake' param with your post, this is not really a problem though, you can just use a hidden input field for it.
You can return the same view from multiple controller actions, but each controller action requires a unique URL:
public class HomeController : Controller {
public ActionResult Index() {
return View("home");
}
public ActionResult About() {
return View("home");
}
}
If you want a link to load up content from a different page without changing the URL, you'll have to use some Ajax to call the server for the content and update the parts of the page you need to change with the new content.
I don't know why you would like to do that, but you could have an Ajax.Actionlink which renders the Details View..
There is almost no reason to hide an URL, not sure what you would like to to.. maybe you explain further that someone can give a better approach.
You can use a good old Server.Transfer for this. However, I'd suggest doing it like has been detailed in this SO post. This gives you an easy way to return an ActionMethod from your current action without peppering your code with Server.Transfer() everywhere.
You can do this by rendering partials- I do this to load different search screens. Sample code is as follows (this is slightly different to my actual code, but you'll get the idea):
<% Html.RenderPartial(Model.NameOfPartialViewHere, Model.SomeVM); %>
Personally though, I don't see why you don't just change the URL?

Resources