Redirecting to action with a parameter - asp.net-mvc-3

Let's say I have a website that displays info about books. The info about a specific book can be seen on a page with the url "/Book/Show/1234", where 1234 is the id of the book.
To edit the information about the book, there's a link on the book page that goes to "/Book/Edit/1234".
When done editing, I wan't to redirect the user back to the book page, i.e. back from "/Book/Edit/1234" to "/Book/Show/1234".
My problem is the going back part. I'm trying to use the RedirectToAction() method. I can specify which controller and which action in that controller to direct to (the "/Book/Show" part), but I don't know how to specify the id of the book to go to, i.e. the last part of the url.
The Edit action method recieves the id as a parameter, so I have access to it. I have tried this without success:
return RedirectToAction("Show", "BookController", id);
This redirects to the url "/Book/Show/". As you can see there is no id.
What is a good way to accomplish what I need?

Try this:
return RedirectToAction("Show", "BookController", new { id = bookId});
where bookId is ID of your book. And Show action looks like:
public ActionResult Show (string id) { ... }

Related

Dynamic Controllers in CodeIgniter

I am in the process of creating a new website which loads all master and child categories from the database. I have tested the navigation as well, i.e., if I click any master category, it perfectly loads all the respective child categories without any issue. However, at present, I am doing this by passing query string in the URL. For instance
http://localhost/MyController?id=32145
Let's assume that the id, 32145, represents a master category namely 'About us'. My question is how can I change the above URL to something like:
http://localhost/Aboutus
and if there is any child category under About us than it should display as:
http://localhost/Aboutus/Mission
Please help me out as I am really stuck with this problem.
by default CodeIgniter uses a segment-based approach, you can do URL routing in way like your second part of the question - "and if there is any child category under About us"
$route['product/(:any)'] = "catalog/product_lookup";
more here: https://ellislab.com/codeigniter/user-guide/general/routing.html
but if you want to rewrite complete URL than you should probably check .htaccess rewriting
It is not easy, do once for migration.
In database you can store the New controller/url for products (if it is not have yet)
Create new Controllers
Route controller which redirect the old Url to the New Url
controllers
Route old urls to Route controller
Route controller something like this:
public function old_url($aProdId) {
if (is_null($aProdId)) {
// error cannot be null
}
$NewUrl = $this->new_url_model->getNewUrl($aProdId);
if (!$NewUrl) {
// error new url not exist
return;
}
redirect(base_url($NewUrl), 'refresh');
}

Spring controller, why is the returned view ignored?

So, say I have an existing, working page Display Cashier, which displays information about a cashier in a shop. Now, I add a button to this page that looks like:
Manager
The request-mapping for this URL maps it (successfully) to a controller: HandleGetManager
the HandleGetManager controller looks like this:
#Controller
public class HandleGetManager{
private employeeBO employeeBO; //BO handles all business logic
//spring hooks
public HandleGetManager(){}
public void setemployeeBo(employeeBO employeeBO){
this.employeeBO = employeeBO;
}
//get controller
#RequestMapping(method=RequestMethod.GET)
public String getManager(#RequestParam String cashierId){
Long managerId = employeeBO.getManagerByCashierId(cashierId);
String redirectUrl = "/displayManager.ctl?managerId=" + managerId.toString();
return redirectUrl;
}
}
Here's what happens when I try it:
I hit the new button on the Display Cashier page, I expect the following to happen:
The browser sends a get request to the indicated URL
The spring request-mapping ensures that the flow of control is passed to this class.
the #RequestMapping(method=RequestMethod.GET) piece ensures that this method is evoked
The #RequestParam String cashierId instructs Spring to parse the URL and pass the cashierId value into this method as a parameter.
The EmployeeBo has been injected into the controller via spring.
The Business logic takes place, envoking the BO and the managerId var is populated with the correct value.
The method returns the name of a different view, with a new managerId URL arg appended
Now, up until this point, everything goes to plan. What I expect to happen next is:
the browsers is directed to that URL
whereupon it will send a get request to that url,
the whole process will start again in another controller, with a different URL and a different URL arg.
instead what happens is:
this controller returns the name of a different view
The browser is redirected to a half-right, half wrong URL: handleGetManager.ctl?managerId=12345
The URL argument changes, but the name of the controller does not, despite my explicitly returning it
I get an error
What am I doing wrong? Have I missed something?
Assuming you have a UrlBasedViewResolver in your MVC configuration, the String value you return is a View name. The ViewResolver will take that name and try to resolve a View for it.
What you seem to want to do is to have a 301 response with a redirect. With view names, you do that by specifying a redirect: prefix in your view name. It's described in the documentation, here.
Here's a question/answer explaining all the (default) ways you can perform a redirect:
How can I prevent Spring MVC from doing a redirect?

MVC & ajax: Should I create more views?

I'm developing an MVC3 application with EF and I wanted to make the UI fluent using jQuery ajax, the user will be able to navigate through the url, if he knows it or maybe he might receive a link pointing to a particular route, but, once the page is fully loaded it needs to be fluent, so I came up with one idea and I would like to discuss it here before I make the changes to the solution.
Here is what I came up with:
TestController.cs (Methods code has been omitted for simplicity)
public ActionResult Index() { ... }
public ActionResult Create() { ... }
[HttpPost]
public ActionResult Create(Test test) { ... }
public ActionResult Update(int testID) { ... }
[HttpPost]
public ActionResult Update(Test test) { ... }
public ActionResult Delete(int testID) { ... }
[HttpPost]
public ActionResult Delete(Test test) { ... }
So far it looks like most controllers. My views are as follows:
Views\Test\List.cshtml
Views\Test\Create.cshtml
Views\Test\Details.cshtml
Views\Test\Delete.cshtml
Now since I wanted to do it async: I've changed my List view so I could add, modify and remove from the list, so far is working like a charm. Plus, the user could still be able to navigate through the application using the url's, note that every link inside the application will perform an ajax request to do the actual work, there are no Route/Action links.
By now the application is working as expected, but now I came across something: there are views that I need to be ActionResult and PartialViewResult, that is because the user could type in the url: "/Admin/Test", which should return the full page, or could click on an anchor which will load only the content of the "/Admin/Test" and display it. To avoid the famous page inside page errors I wrote a function to send the request, and when the request arrives it selects only what I need, avoiding then the page inside page, and to duplicate views, but, the response is the whole page which, I don't need to say, it's not the best option, but since the application will be used by lan I didn't care too much about the payload of the response, but then I needed to write javascript code inside the views, so my solution was like null because using the jQuery selector to get only what I need the javascript wasn't there.
As for my new solution to solve my last solution:
I thought I might leave the original view as is, and create another view appending the word "Partial" after the original name, creating another method in the controller with the same naming convention, plus adding the new Route to my Route Table.
To wrap things up, what I need is the following:
- If the user types in "/Test" the response should be the entire page, loaded like the old days, screens flashing white and such.
- But if the user clicks the Test link in the navigation bar, the response should be async and refreshing only the content of my layout.
Any ideas? thoughts? suggestions?
In your actionmethod you can have
if (Request.IsAjaxRequest())
return PartialView("_somePartialView");
else
return PartialView("_someOtherPartialView");

MVC3 Recommended Controller, Action query re-use

In an MVC3 app what is the recommended method to store the Controller, Action & query details of a page and then re-use them in an actionlink on a subsequent page?
e.g. from page ~/Home/BlogsByTag?tag=Cloud%20Services listing a series of blogs, what is the 'best' way to capture the Controller, Action & query and then how can these then be applied to a 'Back to List' actionlink in a subsequent edit page (~/Admin/Edit/?Blog=1234)?
If i understand you right, you want to generate an ActionLink with the url from the referring page?
You can read the referrer from the request in terms of a complete url:
Request.UrlReferrer
If you want to have access to the action, controller and query parts, you have to pass them in the link as parameters. For example:
Html.ActionLink("Linktext", "Edit", "Admin", null,
new {
Blog = 1234,
ReferringController = "Home",
ReferringAction = "BlogsByTag",
ReferringQueryParams = ...
});
Then you can read that vals in the Edit Action and pass it to the View to generate the back-link.
But maybe using history.back() is a simpler approach.
You can use:
Url.RouteCollection["controller"]
Url.RouteCollection["action"]
...
For the variables you need. For the querystring you can use:
Request.QueryString["variable1"]
Alternatively you can declare the controller:
public ActionResult MyController(string controller, string action, string variable...)
and the variables will be automagically filled.
Then you can store this info (or the full url) on Session["refurl"] for example, which is valid for the rest of the user's session

Need help with ReturnUrl in MVC 3 LoginPage

I have this url in my login view: http://localhost:5550/login?ReturnUrl=/forum/456&theme=1
I get the right url value when I am in the login page.
As you can see I have 2 query string parameters: ReturnUrl and theme
So far good.
Now the login page posts a form to a controller action.
All I need is to read the values of these 2 query string params.
I just can't make it work.
This is my login page view:
#using (Html.BeginForm("try", "login"))
{
//set text boxes and button so user can try login
}
This is my controller where I need those 2 values:
[HttpPost]
public ActionResult Try(LoginModel model, string ReturnUrl, string theme)
{
//read all query string param values...but how?
//I am not getting anything in string ReturnUrl, string theme. They are null
}
Other part of the question:
I can debug other controller. But not this controller.
Is this because I am posting a form using BeginForm?
Doesn't make sense. But the breakpoint never hits even though I get error on browser.
Normally you shouldn't be reading from ReturnUrl. The flow works like this:
Request to controller action which requires authentication using the [Authorize] attribute
ASP.NET MVC adds the ReturnUrl and redirects to /Account/LogOn, automatically encoding and appending the ReturnUrl parameter
The Account/LogOn POST controller action, after authenticating the login information, redirects to the URL in the ReturnUrl.
I wrote about that in gory detail in the following posts:
Looking at how the ASP.NET MVC Authorize interacts with ASP.NET Forms Authorization
Preventing Open Redirection Attacks in ASP.NET MVC
The second post indicates one good reason why need to be careful with ReturnUrl - users can tamper with them.
In the example you showed above, I'd expect that, after authorization, the user would be redirected to the Forum / Index action, which would then be reading the values. If you are creating the ReturnUrl, you should be URL Encoding the second &.
Not sure on the exact reason the values don't get bound, but the easy workaround is to add those properties to your login model and add hidden fields on the form.
Try changing the decoration:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Try(LoginModel model, string ReturnUrl, string theme)
{
//read all query string param values...but how?
//I am not getting anything in string ReturnUrl, string theme. They are null
}

Resources