ASP.Net MVC: Passing a string parameter to an action using RedirectToAction() - asp.net-mvc-3

I would like to know how to pass a string parameter using RedirectToAction().
Let's say I have this route:
routes.MapRoute(
"MyRoute",
"SomeController/SomeAction/{id}/{MyString}",
new { controller = "SomeController", action = "SomeAction", id = 0, MyString = UrlParameter.Optional }
);
And in SomeController, I have an action doing a redirection as follows:
return RedirectToAction( "SomeAction", new { id = 23, MyString = someString } );
I tried this redirection with someString = "!##$%?&* 1" and it always fails, no matter if I encode the string. I tried encoding it with HttpUtility.UrlEncode(someString), HttpUtility.UrlPathEncode(someString), and with Uri.EscapeUriString(someString) to no avail.
So I resorted to us TempData to pass someString, but still, I would be curious to know how to make the code above work, just to satisfy my curiosity.

I think the issue might be either in your route order, or in your controller. Here is some code that I got to work.
Route Definitions
routes.MapRoute(
"TestRoute",
"Home/Testing/{id}/{MyString}",
new { controller = "Home", action = "Testing", id = 0, MyString = UrlParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
// note how the TestRoute comes before the Default route
Controller Action Methods
public ActionResult MoreTesting()
{
return RedirectToAction("Testing", new { id = 23, MyString = "Hello" });
}
public string Testing(int id, string MyString)
{
return id.ToString() + MyString;
}
When I browse to /Home/MoreTesting I get the desired output of "23Hello" to output in my browser. Can you post your routes and your Controller code?

OK, I know this question is a few days old but I wasn't sure if you got this issue sorted or not so I had a look. I played around with this for a while now and this is what the problem is and how you could solve it.
The problem you are having is that the special characters causing issues are one of the many (I think 20) special characters, such as % and ".
In your example the problem is the % character.
As pointed out by Priyank here:
The route values are posted as part of the URL string.
The Url string (not query string parameter) can't handle %(%25), "(%22) and so on.
Further, as pointed out by Lee Gunn in the same post:
http://localhost:1423/Home/Testing/23/!%40%23%24%25%3f%26*%201 - (this will blow up)
One of the ways to fix this is to remove {MyString} from the route mapping. To make your root mapping look like this:
routes.MapRoute(
"TestRoute",
"Home/Testing/{id}",
new { controller = "Home", action = "Testing", id = 0, MyString = UrlParameter.Optional }
);
This will cause the post to generate this:
http://localhost:1423/Home/Testing/23?MyString=!%2540%2523%2524%2525%2B1
Now when you set MyString it will be turned into a query string parameter which works perfectly fine.
I did try that and it did work.
Priyank also mentioned in the SO post I linked above that you maybe could solve this with a custom ValueProvider but you would have to follow his linked article their to check if that is something that would apply to you.

Related

Why was no action found for route?

My WebApiConfig.cs contains just this one route:
config.Routes.MapHttpRoute(
name: "Calendar",
routeTemplate: "api/Calendar/{date}",
defaults: new { controller = "Calendar", action = "Get", date = RouteParameter.Optional }
);
And my CalendarController class has only this method:
public IEnumerable<FVEvent> Get( string dateStr )
{
return db.Events.ToList();
}
But when I try hitting /api/Calendar in the browser, I get the following MessageDetail in the XML:
No action was found on the controller 'Calendar' that matches the request.
Plus I don't know why it's XML, I'd like it to be JSON.
There's just so much hidden magic going on I can't make a slight adjustment to a simple example without everything falling apart.
Your route marks the dateStr parameter as optional, but the method signature does not. Try adding a default value to your dateStr parameter:
public IEnumerable<FVEvent> Get(string dateStr = "")
{
return db.Events.ToList();
}
Make sure the name of your Calendar Controller ends with Controller. Also use the following code in your WebAPI config to remove the XML formatter.
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);

ASP.NET MVC Routing wrong

I'm having some troubles when trying to use routes in ASP.NET MVC 3.
I'm in this URL:
mysite/InitialPage/123456 <- partner ID
Routing it...
routes.MapRoute(
"InitialPageRoute",
"InitialPage/{partnerID}",
new { controller = "InitialPage", action = "Index" }
);
OK, it works fine.
When I put a Html.ActionLink to redirect to another page...
#Html.ActionLink("Another copy of some bill", "CopyOfBill", "Payment", new { partnerID = ViewBag.PartnerID })
And routing this way...
routes.MapRoute(
"CopyOfBillRoute",
"Payment/CopyOfBill/{partnerID}",
new { controller = "Payment", action = "CopyOfBill" }
);
And doesn't work.
Anyone have any idea?
Thanks!!!
It might be best to use a RouteLink in this case (name the route explicitly), since both the controller and action are hard-coded.
#Html.RouteLink("Another copy of some bill", "CopyOfBillRoute",
new { partnerID = ViewBag.PartnerID })
Use this overload
public static MvcHtmlString ActionLink(
this HtmlHelper htmlHelper,
string linkText,
string actionName,
string controllerName,
Object routeValues,
Object htmlAttributes
)
So your code will be
#Html.ActionLink("Another copy of some bill", "CopyOfBill", "Payment",
new { partnerID = ViewBag.PartnerID },null)
Assuming you do not want to specify any HTML attributes for the anchor tag. If you want, replace the last parameter (null) with the HTML Attributes.
first you write your route in Global.asax at the top . top you make your first route
routes.MapRoute(
"CopyOfBillRoute",
"Payment/CopyOfBill/{partnerID}",
new { controller = "Payment", action = "CopyOfBill" }
);
and use your route like this
#Html.RouteLink("click", "Regis",new {id=>id.Id})
i think this will help you

url parameters missing after adding a comment and redirecting back to blog post

I am teaching myself asp .net mvc3 by creating a blog application. However, I have
problems with comment upload. It is a very subtle error in that everything works when a user leaves a comment. However, the url of the post changes.
So, a blog post has a url
http://localhost:49175/Blog/Details/3/Third-post
This is generated by the url route map here:
routes.MapRoute(
"BlogDetail", // Route name
"Blog/Details/{id}/{urlHeader}", // URL with parameters
new { controller = "Blog", action = "Details", id = UrlParameter.Optional, urlHeader = UrlParameter.Optional } // Parameter defaults
);
Now, when a user leaves a comment - he is directed to a comment controller:
[HttpPost]
public ActionResult Create(BlogDetailsViewModels viewModel)
{
if (ModelState.IsValid)
{
try
{
blogrepository.Add(viewModel.Comment);
return RedirectToAction("Details", "Blog", new { id = viewModel.Comment.BlogID });
}
catch (DataException)
{
ModelState.AddModelError("", "Unable to save comment. Try again, and if the problem persits then contact administrator.");
}
}
// If we got this far, something failed, redisplay form
return RedirectToAction("Details", "Blog", new { id = viewModel.Comment.BlogID });
}
}
However, when somebody leaves a comment - he is redirected back to
http://localhost:49175/Blog/Details/3
I know, as of now there is nothing in the RedirectToAction that passes the urlHeader info. However, I have tried a few things like:
return RedirectToAction("Details", "Blog", new { id = viewModel.Comment.BlogID, urlHeader = viewModel.Blog.UrlHeader });
However, it doesn´t seem to work.
This is the blog details controller:
//
// GET: /Blog/Details/5
public ViewResult Details(int id, string urlHeader)
{
var blogs = blogrepository.GetBlog(id);
var recentblogs = blogrepository.FindRecentBlogs(5);
var archivelist = blogrepository.ArchiveList();
BlogDetailsViewModels viewModel = new BlogDetailsViewModels { Blog = blogs, RecentBlogs = recentblogs, ArchiveList = archivelist };
return View(viewModel);
}
I am stuck for days on this.
-- Full route method as requested --
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"BlogDetail", // Route name
"Blog/Details/{id}/{urlHeader}", // URL with parameters
new { controller = "Blog", action = "Details", id = UrlParameter.Optional, urlHeader = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"BlogArchive", // Route name
"Blog/{year}/{month}", // URL with parameters
new { controller = "Blog", action = "Archive" }, // Parameter defaults
new { year = #"\d{4}", month = #"\d{1,2}", } // Parameter constraints
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
If your form does not contains data for viewModel.Blog.UrlHeader, it will be an empty string, even viewModel.Blog may be null.
You can add a parameter to your post action method, like this:
[HttpPost]
public ActionResult Create(BlogDetailsViewModels viewModel, String urlHeader)
And, in your view that renders the form, use this code to generate the form element:
#Html.BeginForm("Create","Blog",new{urlHeader=Model.Blog.UrlHeader})
Alternatively, you can add a hidden input in your form for the urlHeader. In this way, you don't have to do any of previous two updates.
#Html.HiddenFor(m=>m.Blog.UrlHeader)
Either way, make sure your Model.Blog.UrlHeader is not null or an empty string

ASP.NET MVC basic routing with parameters

I have been trying to learn ASP.NET MVC 3 and things are going well apart from the routing aspect, whatever I try I just can't seem to get them quite right.
I have an ActionLink on the main page:
#Html.ActionLink("Contracts", "List", "Contract",
new { User.Identity.Name, page=1 })
Which is meant to access this method in the ContractController:
public ViewResult List(string user, int page = 1)
{
//snip
}
My routes are:
routes.MapRoute(
null,
"Page{page}",
new { Controller = "Contract", action = "List" }
);
routes.MapRoute(
null,
"Page{page}",
new { Controller = "Contract", action = "List", user = "", page = 1 }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
The link now will return a 404 error as it can't find the action 'List' in the controller 'Home', which obviously means it didn't use either of the first routes.
Everything worked before I tried to add parameters to the ActionLink, so basically, what am I doing wrong?
Thanks very much.
Alex,
You're doing all the other bits absolutely correctly, however the actionlink has a missing parameter, try this for your actionlink:
#Html.ActionLink("Contracts", "List", "Contract",
new { User.Identity.Name, page = 1 }, null)
Adding the null as the final param (htmlAttributes) is all that's missing for you in this scenario (there are 9 overloads for Html.ActionLink, so it's VERY easy to miss the correct implementation).

Issue With ViewBag and Routes (MVC 3 - RC2)

I am having an issue with MVC-3 generating outgoing routes for me.
This is the address of the page I am on for both scenarios: http://localhost:1283/Conflict/Create/1200/300
Here are the map routes:
routes.MapRoute(
null, // Route name
"{controller}/{action}/{custId}/{projId}", // URL with parameters
null, // Parameter defaults
new { custId = #"\d+", projId = #"\d+" }
);
routes.MapRoute(
null, // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Scenario 1:
From the controller:
public ActionResult Create(int custId, int projId)
{
return View();
}
From the view:
#Html.ActionLink("Back to List", "Index", "Conflict", new { custId = ViewBag.custId, projId = ViewBag.projId }, null)
The resulting link that gets created.
http://localhost:1283/Conflict?custId=1200&projId=300
If I change the controller code to read as follows:
public ActionResult Create(int custId, int projId)
{
ViewBag.custId = custId;
ViewBag.projId = projId;
return View();
}
I didn't make any changes in the view, only added those two lines to the controller and the following link is created:
http://localhost:1283/Conflict/Index/1200/300
What am I missing here? This is consistent behavior, I was able to reproduce this in other areas of my application. The "solution" is obvious, but my question is why?
What's happening is the "?custId=1200&projId=300" part of your link is coming over from the link you used to GET the page you're on. So the Html.ActionLink call is doing this:
generate the /Conflict/Index path
look for the custId and projId in the ViewBag and finds the query string instead
just appends your query string
In the second scenario, you're actually providing values, so the link is generating normally. Hope that helps.

Resources