Html.BeginForm routing to Web Api - c#

I am trying to get my page to post to my Web API controller, rather than my Area/Controller/Action. Here is what I have so far, I have tried using both Html.BeginForm and Ajax.Begin Form :
#using (Ajax.BeginForm("", "", null, new AjaxOptions { HttpMethod = "POST", Url = "api/Standing" }, new { id = "frmStandingAdd", name = "frmStandingAdd" }))
#using (Html.BeginForm("", "api/Standing", FormMethod.Post, new { id = "frmStandingAdd", name = "frmStandingAdd" }))
But I cannot get either to post to the root ie http://domain/api/Standing, instead both post to the Area ie http://domain/Areaname/api/Standing. How do I get it to post correctly?
Update: Here are my routes for the relevant area :
public override string AreaName
{
get
{
return "Areaname";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
string defaultLocale = "en-US";
context.MapRoute(
"Areaname_default",
"{languageCode}/Areaname/{controller}/{action}/{id}",
new { languageCode = defaultLocale, controller = "Main", action = "Index", id = UrlParameter.Optional });
context.MapRoute(
"History",
"{languageCode}/Areaname/{controller}/{action}/{year}",
new { controller = "History", action = "Season", year = UrlParameter.Optional });
}
And my Web API routes :
config.Routes.MapHttpRoute(
"DefaultApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
"DefaultApiWithAction",
"api/{controller}/{action}/{season}",
new { id = RouteParameter.Optional }
);

You can explicitly tell the links to post to the root by including the leading slash:
#using (Ajax.BeginForm("", "", null, new AjaxOptions { HttpMethod = "POST", Url = "/api/Standing" }, new { id = "frmStandingAdd", name = "frmStandingAdd" }))
#using (Html.BeginForm("", "/api/Standing", FormMethod.Post, new { id = "frmStandingAdd", name = "frmStandingAdd" }))

You would need to use BeginRouteForm as link generation to Web API routes always depends on the route name. Also make sure to supply the route value called httproute as below.
#using (Html.BeginRouteForm("DefaultApi", new { controller="Entries", httproute="true" }))

Related

ASP.NET MVC Routing 404 error

First I want to show code
routes.MapRoute(
name: "SubCategory",
url: "Category/{categoryName}/{subName}",
defaults: new { controller = "Categories", action = "SubCategory", categoryName = "", subName = "" }
);
this is my route
categoryName and subName are variables
// GET: Category/{categoryName}/{subName}
public ActionResult SubCategory(string categoryName, string subName)
{
CategoriesViewResult viewResult = new CategoriesViewResult();
viewResult.Categories = _db.Categories.ToList();
viewResult.CurrentSubCategory = _db.SubCategories.First(x => x.Category.CategoryName == categoryName && x.SubCategoryName == subName);
return View(viewResult);
}
this is my method;
but I get 404.
how should i write my routes.
UPDATE
this is above default route.
Try it like this
routes.MapRoute(
"SubCategory",
"Category/Sub/{categoryName}/{subName}",
new { controller = "Categories", action = "SubCategory", apiId = UrlParameter.Optional }
);
Also, which version of MVC are you using?

"routes.LowercaseUrls = true;" does not work?

I'm having trouble in setting my routes to lowercase by default. For some reason it does not work. I know I can set authorize and home to lowercase myself, but the Admin part (area) will still be capitalized..
#Html.ActionLink("Hello World", "Authorize", "Home")
outputs to
Hello World
Area route
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.LowercaseUrls = true;
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new string[] { "OR.Areas.Admin.Controllers" }
);
context.Routes.LowercaseUrls = true;
}
Default route
public static void RegisterRoutes(RouteCollection routes)
{
routes.LowercaseUrls = true;
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.LowercaseUrls = true;
routes.MapRoute(
name: "Localization",
url: "{lang}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "OR.Controllers" }
);
routes.LowercaseUrls = true;
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "OR.Controllers" }
);
routes.LowercaseUrls = true;
}
Admin Area configs I tried
// admin/Home/Authorize
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.LowercaseUrls = true;
context.MapRoute(
"Admin_default",
"{area}/{controller}/{action}/{id}",
new { area = "admin", controller = "home", action = "Index", id = UrlParameter.Optional },
new string[] { "ORMebeles.Areas.Admin.Controllers" }
);
context.Routes.LowercaseUrls = true;
}
// admin/Home/Authorize
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.LowercaseUrls = true;
context.MapRoute(
"Admin_default",
"admin/{controller}/{action}/{id}",
new { controller = "home", action = "Index", id = UrlParameter.Optional },
new string[] { "ORMebeles.Areas.Admin.Controllers" }
);
context.Routes.LowercaseUrls = true;
}
Edit
As it seems this is bug with MVC4 - when you set context.Routes.LowercaseUrls = true; and you have Area/Areas context.Routes.LowercaseUrls = true; won't take any effect, where should we report it or how can we get it fixed?
This is bug related to MVC4 and will be fixed in MVC5 release. Routes.LowercaseUrls does not affect areas. More info here.
Meanwhile you can use LowercaseRoutesMVC or
LowercaseRoutesMVC4 if you need WebApi support.
I tried Several attempts to get this particular boolean flag to work with an MVC3 project with no luck. The ONLY way I could get it to work was to create an MVC4 application project and set the flag in the RouteConfig.cs file in the app start. The really bad part is it lowercased the urls across the site automatically for me until I added an area, then it broke everywhere. Once I excluded the newly added area from the project and reran, the urls were lowercased again.
Something is wonkey with the use of that flag. I would recommend downloading the nuget package for lowercasing urls. It seems as if they haven't quite worked out the kinks in this part of the new framework.
Sorry I couldn't be of more help.
UPDATE: IN AN MVC4 application
Create a new blank MVC4 application and add an Area Called Test, with a Test.cshtml View and a TestController.cs controller.
So I figured out something... though I am not sure if it's a reasonable solution. After playing with the route registration routines, having the areas in the project doesn't break the lowercase functionality.
namespace MvcApplication1.Areas.Test
{
public class TestAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Test";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
//This line breaks the functionality in the area registration.
context.MapRoute(
"Test_default", // Route name
"Test/{controller}/{action}/{id}", // URL with parameters
new { controller = "Test", action = "Index", id = "" }, // Parameter defaults
new string[] { "MvcApplication1.Areas.Test.Controllers" } //namespace
);
}
}
}
A workaround:
Comment out the lines
//context.Routes.LowercaseUrls = true;
//context.MapRoute(
// "Test_default", // Route name
// "Test/{controller}/{action}/{id}", // URL with parameters
// new { controller = "Test", action = "Index", id = "" }, // Parameter defaults
// new string[] { "MvcApplication1.Areas.Test.Controllers" } //namespace
// );
In RouteConfig.cs
namespace MvcApplication1
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.LowercaseUrls = true;
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"Test_default", // Route name
"Test/{controller}/{action}/{id}", // URL with parameters
new { controller = "Test", action = "Index", id = "" }, // Parameter defaults
new string[] { "MvcApplication1.Areas.Test.Controllers" } //namespace
);
}
}
}
In The Area Controller Action Method
public ActionResult Index()
{
// Key if statement to make sure the area maps correctly
if (!this.ControllerContext.RouteData.DataTokens.ContainsKey("area"))
{
this.ControllerContext.RouteData.DataTokens.Add("area", "Test");
}
return View("Test");
}
Resulting HTML for the links in the main page of the project
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
<li>Test</li>
</ul>
Notice however the query string variables are not lowercased and it is not an seo friendly url. However it does find the view. This is as close as I've been able to come using that flag and having the urls go to lowercase.
As I known, LowercaseUrls = true is only available in .NET4.5, maybe you can just write some extensions for lowercase urls. you can refer to making URL lowercase. Any easy or builtin way for detail info.

asp.net multiple urls pointing to same controller

I am working on a social networking site where we are implementing profiles, pages, groups etc. At this stage, we are working with profiles and pages. They both have wall where user can put some status, pics etc, more like facebook wall.
Now a controller WallController can be accessed by two different urls.
www.mysite.com/profile/121/some-user/wall
and
www.mysite.com/page/222/some-page/wall
On the left hand side of the page, I load some basic information (name etc) and a menu.
saying
www.mysite.com/profile/121/some-user/photos
www.mysite.com/profile/121/some-user/videos
www.mysite.com/profile/121/some-user/songs
This applies to both (page and profile).
here is my route for page
routes.MapRoute(
"Page-wall", // Route name
"page/{id}/{name}/wall", // URL with parameters
new { controller = "wall", action = "details", id = "", name = "" },
new { id = #"\d+" },
new string[] { "PagesNameSpace.Controllers" } // Parameter defaults
);
and for profile
routes.MapRoute(
"profile-wall", // Route name
"profile/{id}/{name}/wall", // URL with parameters
new { controller = "wall", action = "details", id = "", name = "" },
new { id = #"\d+" },
new string[] { "ProfileNameSpace.Controllers" } // Parameter defaults
);
Now, the problem is, I have to identify what object is accessing the url. here is my WallController
public class WallController : Controller
{
public ActionResult Details(long id, string name)
{
return View(LoadWallData(id));
}
}
I see a route value dictionary as a solution, but would like to see, what is the best solution for this kind for situations.
help will be appreciated.
Regards
Parminder
I would probably do the following, you just add the values into your routes:
Change your controller:
public class WallController : Controller
{
public ActionResult Details(long id, string name, string obj)//added param
{
return View(LoadWallData(id));
}
}
And then your routes:
routes.MapRoute(
"Page-wall", // Route name
"page/{id}/{name}/wall", // URL with parameters
new { controller = "wall", action = "details", id = "", name = "",
/*See this>>>> */ obj="page"},
new { id = #"\d+" },
new string[] { "PagesNameSpace.Controllers" } // Parameter defaults
);
routes.MapRoute(
"profile-wall", // Route name
"profile/{id}/{name}/wall", // URL with parameters
new { controller = "wall", action = "details", id = "", name = "",
/*See this>>>> */ obj="profile" },
new { id = #"\d+" },
new string[] { "ProfileNameSpace.Controllers" }
);
using ((System.Web.Routing.Route)(Url.RequestContext.RouteData.Route)).Url you can get the URL with parameter values from MapRoute.
I feel, I would go with this approach.
public class WallController : Controller
{
public ActionResult Details(string type ,long id, string name)//added param
{
return View(LoadWallData(id));
}
}
and my routes
routes.MapRoute(
"wall-default", // Route name
"{type}/{id}/{name}/wall", // URL with parameters
new { controller = "wall", action = "details", id = "", name = "",
type="profile"},
new { id = #"\d+" },
new string[] { "PagesNameSpace.Controllers" } // Parameter defaults
);
Now just by passing the type parameter, I can get action link for page and profile.
thanks a lot to everyone.
Regards

Creating an Html.ActionLink to a dynamic content page

I have functionality on my site to create/edit/delete pages for the front end. Here's my controller:
namespace MySite.Controllers
{
public class ContentPagesController : Controller
{
readonly IContentPagesRepository _contentPagesRepository;
public ContentPagesController()
{
MyDBEntities entities = new MyDBEntities();
_contentPagesRepository = new SqlContentPagesRepository(entities);
}
public ActionResult Index(string name)
{
var contentPage = _contentPagesRepository.GetContentPage(name);
if (contentPage != null)
{
return View(new ContentPageViewModel
{
ContentPageId = contentPage.ContentPageID,
Name = contentPage.Name,
Title = contentPage.Title,
Content = contentPage.Content
});
}
throw new HttpException(404, "");
}
}
}
And in my global.asax:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Page", // Route name
"Page/{name}", // URL with parameters
new { controller = "ContentPages", action = "Index" }, // Parameter defaults
new[] { "MySite.Controllers" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new[] { "MySite.Controllers" }
);
}
So I have a dynamic page in my database, named About. If I go to mysite.com/Page/About, I can view the dynamic content.
I want to create an ActionLink to this page. I've tried it like this:
#Html.ActionLink("About Us", "Index", "ContentPages", new { name = "About" })
But when I look at the link on the page, the url just goes to the current page with Length=12 in the query string. For instance, if I'm on the homepage, the link goes to mysite.com/Home?Length=12
What am I doing wrong here?
You are not using the correct ActionLink overload. Try like this:
#Html.ActionLink(
"About Us", // linkText
"Index", // action
"ContentPages", // controller
new { name = "About" }, // routeValues
null // htmlAttributes
)
whereas in your example:
#Html.ActionLink(
"About Us", // linkText
"Index", // action
"ContentPages", // routeValues
new { name = "About" } // htmlAttributes
)
which pretty obviously explains why your doesn't generate the expected link.

Language in URL, Routing and Areas

I've learned so far how to set up a correct routing if I would like to have the language within the URL, e.g. .../en/MyController/MyMethod. With the following routing this works great so far:
routes.MapRoute("Default with language", "{lang}/{controller}/{action}/{id}",
new
{
controller = "Report",
action = "Index",
id = UrlParameter.Optional,
}, new { lang = "de|en" });
// Standard-Routing
routes.MapRoute("Default", "{controller}/{action}/{id}", new
{
controller = "Report",
action = "Index",
id = UrlParameter.Optional,
lang = "de",
});
Now I Inserted a new area Cms, and I call AreaRegistration.RegisterAllAreas(); in Application_Start().
As soon as I call a controller within this area, I miss the language-key:
MvcHandler handler = Context.Handler as MvcHandler;
if (handler == null)
return;
string lang = handler.RequestContext.RouteData.Values["lang"] as string;
How could I make the above routing work with areas?
Thx for any tipps, sl3dg3
Check out the generated class that derives from AreaRegistration, named [AreaName]AreaRegistration.
It contains a route registration as well, this is the default:
context.MapRoute(
"AreaName_default",
"AreaName/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
The following routing works now in my case (the area is called Cms):
using System.Web.Mvc;
namespace MyProject.Areas.Cms
{
public class CmsAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Cms";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute("Cms_default_with_language", "Cms/{lang}/{controller}/{action}/{id}", new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
lang = "de",
}, new { lang = "de|en" });
context.MapRoute(
"Cms_default",
"Cms/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional, lang = "de" }
);
}
}
}
The only thing I'm not quite happy about: now I have more or less duplicate code in Global.asax and in this class. Is there a way to avoid these duplicate mappings?

Categories

Resources