I am currently trying to redirect to the Index of one controller (the Company controller) from a second controller (the Search controller). In my Search controller, I have the following code:
RedirectToAction("Index", "Company", new { id = redirectTo.Id, fromSearch = true, fromSearchQuery = q })
But unfortunately, this takes me to:
/Company/Index/{id}?fromSearch=true&fromSearchQuery={q}
Where fromSearch and fromSearchQuery are optional parameters that are not always used.
Is there a way to either directly get the URL from RedirectToAction so I can encase it in a Redirect after I chop out the Index part of the string, or set up routes with the optional parameters?
If you want just the URL you can use the Url.Action
helper which takes all the same parameters but just returns the URL.
However, creating routes with optional segments followed by additional segments is more difficult because omitting a segment in the middle will just cause all the other segments to shift down and you'll wind up with your id
taking the place of your action
. The solution is to create a route that matches the number of segments, and position of the segments, when the optional value is omitted. You can also use route constraints to further restrict what the route matches.
For example, you could create this route:
routes.MapRoute(
name: "IndexSearch",
url: "{controller}/{id}",
defaults: new { action = "Index" },
constraints: new { action = "Index" }
);
Coupled with the default route after it:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Would result in the helper call:
RedirectToAction("Index", "Company", new { id = redirectTo.Id, fromSearch = true, fromSearchQuery = q })
Creating the URL: /Company/{id}/?fromSearch=true&fromSearchQuery=q when the action
is Index or the action is omitted. If the action is provided and is something other than Index than routing will defer to the default route.
You need to route your request properly because you're providing search parameters as query string. Just have one search route as below:
routes.MapRoute(
"CompanySearch",
"Company/{id}",
new { controller = "Company", action = "Index" }
);
Then write this controller action
public ActionResult Index(bool fromSearch, string fromSearchQuery)
{
// do other stuff
}
You could of course create a class that could be validated, but property names should reflect that of the query string. So you'd either have a class:
public class SearchTerms
{
public bool FromSearch { get; set; }
public string FromSearchQuery { get; set; }
}
And use the same request with equally named query variables as you do now, or have a clean class and adjust your request:
http://domain.com/Company/{id}?FromSearch=true&fromSearchQuery=search+text
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With