ASP.NET MVC Render Form With Route Values - asp.net

The route for my view is like this:
http://localhost/project1/join/register/ABCDEFGH/12345678
The last two parts are the parameters which I accept as part of my route. What I want to do now is to render a form onto the view which has a post method which retains that url.
I am using the BeginForm HTML helper as follows:
using (Html.BeginForm(
"Register",
"Join",
new { ApplicationKey = Model.ApplicationKey, UserId= Model.UserId},
FormMethod.Post,
new { #class = "form-horizontal", #role = "form" }))
This renders the forms action tag with a URL as follows...
http://localhost/project1/join/register?ApplicationKey=ABCDEFGH&UserId=12345678
Is there any way to use the form helper and to retain the format of my route? I can make this work with query string parameters but there are other considerations which mean it would be better if I could get the helper to format the route as it was originally used to access the page.
Thanks.

The reason it isn't formatted nicely is because it hasn't found a matching route that fits all the parameters being passed.
You could try Html.BeginRouteForm and use a named route to do it.
http://msdn.microsoft.com/en-us/library/system.web.mvc.html.formextensions.beginrouteform(v=vs.118).aspx

Related

ASP Mvc Ajax.BeginForm doesn't post File and Html.BeginForm breaks the design?

I've trying to send a file through Ajax.beginForm with enctype = "multipart/form-data", but I always get it as null,
I'm returning a JavaScriptResult from My controller like this,
public JavaScriptResult SaveFile(MyModel model)
{
JavaScriptResult result = new JavaScriptResult();
result.Script = "$('#ShowPopup').trigger('click')";
return result;
}
When using Html.BeginForm it works great, but when it returns the result, it shows the following on the browser,
I don't know what's wrong with Html.BeginForm(), also when I'm returning a view, the view returns but without the my _Layout.cshtml page, breaks my design,
so the problem is when I use ajax it perfectly great but doesn't post file,
and when I'm using html.beginForm, it posts the file, but breaks the design after return.

ASP.NET MVC 4 C# - Get Sectioned Elements or full URL to Parse

Being kind of a newb to MVC 4 (or really any of the MVC's for ASP.NET) I cant help but feel theres more to the URL helper than what I'm seeing.
Basically I've read the tutorials on populating the attributes in a controllers methods using a query string in the URL.
I dont liek query strings though and prefer a sectioned "folder" like style.
Without much further adu, this is the sample URL:
http://something.com/DataTypes/Search/searchString
this approach is actually pretty safe as there will only ever be single worded searches
I have tried in the DataTypes controller
[HttpGet]
public ActionResult Search(String q)
{
ViewBag.ProvidedQuery = q;
return View();
}
and a few other small variations, right now im just trying to get the string to show up in the view but I dont seem to be getting anything there.
Is there anyway to inject the 3rd string in the url into an attribute?
If not, which URL helper class am I supposed to use to acquire the string data in the URL? Even if I have to parse the whole URL manually so be it, i just need to acquire that 3rd element in the URL as a string
Extremely n00b question im sure, but either im not finding this simple guide somewhere, or im not searching google correctly...
What you're missing is that the default route parameter name is "id". So you want to do this:
[HttpGet]
public ActionResult Search(String id)
{
ViewBag.ProvidedQuery = id;
return View();
}
If you don't want to use the variable name id, then you can modify your Route to look like this:
routes.MapRoute(
name: "Search",
url: "DataTypes/Search/{searchString}",
defaults: new { controller = "DataTypes", action = "Search",
searchString = UrlParameter.Optional });
If you don't want the string to be optional, then you can remove the last field from the defaults object.
you can use RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext)) to get the routedata
String URL to RouteValueDictionary
You need to look at the routing in the Global.asax.cs. For example for your case you could add a route to the routes collection like this:
routes.MapRoute("Search",
"DataTypes/Search/{q}",
new { controller = "DataTypes", action = "Search" }
);
Then the q parameter will automatically get mapped to your action. The default controller mapping is likely mapping it to "id".

ASP.MVC routes without Details action

I'd like to have URLs that are even shorter than /{Controller}/{Action}/{Id}.
For example, I'd like {Controller}/{Id}, where {Id} is a string.
This would allow for simple paths, e.g. Users/Username, Pages/Pagename, News/Newsname. I like this better than requiring the /Details action in the URL (Users/Details/Username), which is less elegant for the end-user.
I can easily make this work by setting up custom routes for any controller that I want this level of simplicity for. However, this causes headaches when it comes to implementing other actions, such as {Controller}/{Action}, where {Action} = 'Create', since, in this case the string {Action} conflicts with the string {Id}.
My question: how can I have 'reserved' words, so that if the URL is /News/Create, it is treated as an action, but if the URL is anything else, e.g. /News/A-gorilla-ate-my-thesis, then it is treated as an Id.
I'm hoping I can define this when setting up my routes?
Update:
Using Ben Griswold's answer, I have updated the default ASP.NET MVC routes to be:
routes.MapRoute(
"CreateRoute", // route name
"{controller}/Create", // url with parameters
new { action = "Create" } // parameter defaults
);
routes.MapRoute(
"DetailsRoute", // route name
"{controller}/{id}", // url with parameters
new { action = "Details" } // parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
This works a charm and means, by default, the details pages will use the simplified URL, but I will still be able to target a specific action if I want to (update/delete/details).
Of course, you will need to disallow the reserved "Create" word as an Id, otherwise a user may try to create an article, for example, with the name "Create", which can never be accessed.
This is really nice. If anyone sees that there is something wrong with this approach, chime in, but I like it so far.
I think you're left with creating a route for each reserved word. For example,
routes.MapRoute("CreateRoute",
"{controller}/Create",
new { action = "Create" }
);
would handle /News/Create, /Users/Create, etc. As long as this route is listed before your other custom route, I think you're covered.
I imagine you will need addition routes for various CRUD operations which will follow a similar pattern.

ASP.NET MVC - Get a URL to the current action that doesn't include the passed ID

I have an action in which I want to intercept any possible integer id that comes and place it behind a hash. (I have some Javascript that is handling the id). I am only doing this extra step for the sake of URL-hackers like me who might forget my convention of putting a hash before the id.
Here is my action:
public ActionResult Edit(int? id)
{
if (id != null) return Redirect(Url.Action("Edit") + "/#" + id);
return View();
}
The problem is that the Url.Action method is preserving the passed id. Url.Action("Edit") is returning "{controller}/Edit/{id}". I want it to just return "{controller}/Edit"! (And my code is tacking on an additional "/#{id}").
For example, a request to this URL:
http://localhost:2471/Events/Edit/22
is redirecting to this URL:
http://localhost:2471/Events/Edit/22/#22
when I want it to redirect to this URL:
http://localhost:2471/Events/Edit/#22
I'm frustrated. Does anyone know how to get a URL to the current action that doesn't include the passed id?
One way to do this would be to define a route for the controller action, eg the Route would be defined as "{controller}/{action}/". Then use something similar to the following to build your actual URL:
Url.RouteUrl("MyRoute") + "#" + id
Not the best method, but it works. Maybe someday Microsoft will add fragment support to routing.
I'm not completely sure but could you use the RedirectToAction method ?
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.redirecttoaction.aspx
I'm not 100% sure (and don't have my dev machine to test), but I think you could pass the hash within the id parameter and it would work...eg:
Url.Action("Edit", "Events", new { id = "#" + id });
or you could use RedirectToAction() the same way.
An alternative would be to define a Route {controller}/{Action}/#{id} and then use Url.Route() instead.

How do I change the URLs that Dynamic Data generates me for entity relationships?

I am using ASP.NET Dynamic Data to create a website that has two aspects - a public view, where data can only be viewed, and a admin site where all the CRUD operations happen. I want this to be a single DD website.
I have setup two routes:
routes.Add(new DynamicDataRoute("admin/{table}/{action}.aspx")
{
Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert" }),
Model = model
});
and
routes.Add(new DynamicDataRoute("{table}")
{
Action = PageAction.List,
ViewName = "ListPublic",
Model = model
});
The problem is, when I view my public page, ListPublic (a copy of the original List.aspx), it works fine except the links to the related entity use the URL of admin/Suppliers/Details.aspx?SupplierId=1 ... when what I want them to point to is
Suppliers/Details.aspx?SupplierId=1
How do I control how the URL is rendered out for the relationship in Dynamic Data?
Ok, it turns out with a bit of googling I have helped myself. Seems there is actually a field template for this called ForeignKey.aspx which binds the URL to the value of GetNavigateUrl().
I guess my question now is:
What does GetNavigateUrl do?
What is the best approach to acheive my outcome of havnig a public and private website using dynamic data

Resources