How to create url for MVC action from ApiController? - asp.net

Is there a way to create an url that liks to an MVC action from an ApiController? I see examples of doing this the other way around, to reach ApiController from with MVC using MVC's UrlHelper (http://blogs.msdn.com/b/roncain/archive/2012/07/17/using-the-asp-net-web-api-urlhelper.aspx).
Any help would be greatly appreciated. Thanks.

You can use the Url property on the API controller to find a route to a web api or an MVC controller. Here is an example of creating a link to the default project template MVC method AccountController.Login(string returnURL).
public class SOExampleController : ApiController
{
public SOExample GetSOExample()
{
var url = Url.Route("Default", new {controller = "Account", action = "Login", returnUrl = "hello"});
return new SOExample{URL = url};
}
}
public class SOExample
{
public string URL {get;set;}
}
When ran you get the url value of the "/Account/Login?returnUrl=hello". It looks like you may need to prepend the domain, which should be trivial to find.

Related

Trying to display Custom View in MVC app but it says requested URL not found

I am new to azure, MVC and also ASP.NET. I am writing MVC Cloud service with ASP.NET web role. Please help me with this problem
When I create the application there are default views but I wanted to see my view so I set my view as start page. I also changed the values in RegisterRoutes method
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "User", action = "AddUser", id = UrlParameter.Optional }
);
}
When I run the app, it gives HTTP 404 error because it could not find request URL : /Views/User/AddUser.cshtml
In MVC you don't put the view in the URL to get it rendered.
This won't work: /Views/User/AddUser.cshtml
As you've correctly put in your question the default route is {controller}/{action}/{id} with id being optional.
So assuming that User is your controller, i.e. you have a class called UserController, which looks something like:
namespace My.Controllers
{
public class UserController : Controller
{
which has an action on it called AddUser:
public ActionResult AddUser()
{
// implementation logic
return View();
}
Then the default route will display your view when it processes the URL /User/AddUser
In MVC 5, this looks something like:

Fill a form with ASP.NET MVC Querystring

I want to fill a form with Id and i have made the url in this way
local-host:1613/Patient/Index/1
Where as 1 is the Id. And i want to fill my form with the data of patient with Id 1.
But this below function is not being called in Controller
public ActionResult Index(int id)
{
Patient p = new CEntities().Patients.Find(id);
return View(p);
}
instead, i am getting into
public ActionResult Index()
{
return View();
}
I am newbie in ASP.NET MVC, i have no idea in filling a form with any other way, i found a way but it shows my whole object in query string which is insecure. And this above solution is not working.
Please suggest me good solution.
As far as I know you cannot truly overload action methods in ASP.NET-MVC so there can be only one Index action method(without any additional annotations). Of course you can define few methods with the same name but then you might want to add [HttpPost](or other HTTP method) annotation above the action method to use it for instance after submitting a form.
Making parameter optional might be helpful:
public ActionResult Index(int? id){
if(id.HasValue()){
Patient p = new CEntities().Patients.Find(id);
return View(p);
}
return View();
}
Please take a look: Can you overload controller methods in ASP.NET MVC?
Another advice: try to use scaffolding and see how template does it for you:
1.Right click on a controller folder
2.Add->New Controller
3.Controller with Entity Framework read/write actions(as far as I remember 3rd from the top)
4.Select model class.
5.Select db context(class which maintains connection with database).
6.Ok.
It will generate controller with views, have fun.
local-host:1613/Patient/Index/1
This path should be hitting your action method of:
public ActionResult Index(int id)
Please check your RouteConfig.cs file and make sure you have the default route set up correctly:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Try commenting out your other Index action method "//public ActionResult Index()", and see what happens when trying to go to local-host:1613/Patient/Index/1

ASP.Net WebApi: Invalid URL generated in BeginForm

I'm beginning to use WebApi and I'm having an issue with a URL being incorrectly generated
I have an ApiController like this:
public class EntriesController : ApiController
{
public HttpResponseMessage Post(Entry entry)
{
...
}
}
And I was trying to create a standard controller (i.e. not webapi) in the same project to test this api (I already tested the api with fiddler and everything is ok there).
I assumed I could use the standard HTML helpers like this:
#using (Html.BeginForm("Post", "Entries"))
However this generates the following markup:
<form action="/Entries/Post" method="post">
and I expected it to generate
<form action="/api/Entries" method="post">
What is the correct way to generate the API url from a view?
I am using the default api and controller routes.
Thanks
#using (Html.BeginForm("Post", "Entries"))
You can not put WebAPI controller and method in MVC BeginForm like above. You need to pass MVC Controller and action to the BeginForm.
You can create a WebAPI EntriesController instance in your MVC controller, then use this instance to call the WebAPI method. See below:
//MVC Controller
public class EntriesController : Controller
{
[HttpGet]
public ActionResult Entries()
{
return View();
}
[HttpPost]
public ActionResult Entries(SomeModels model)
{
if (ModelState.IsValid)
{
var api = new EntriesController(); // Create WebAPI instance Here
api.Post(model.entry);
return RedirectToAction("Index", "Home");
}
return View();
}
}
This is technically possible by doing:
#using (Html.BeginForm("Post", "api/Entries"))
Don't forget, the "Post" value in the .BeginForm() extension method doesn't mean anything to an out-of-box Web Api route setup. Only the url and HTTP action matter (and any additional values on the URL for method overloading)
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" }))

Get an instance of WebApi UrlHelper from inside an Mvc Action

I am running WebApi and Mvc from within the same project (so they are in-process). Mvc mostly for serving assets (pages and generated downloads) and web api for ajax data requests.
In order to be RESTish, most of the WebApi requests include a set of links where are generated by the following class:
public class ApiLinkMaker
{
public ApiLinkMaker(UrlHelper url, string authority) {
this.url = url;
this.authority = authority;
}
public ApiLinkMaker(ApiController controller)
: this(controller.Url, controller.Request.RequestUri.Authority) { }
public string MakeLink(string controller, string id) {
return "//" + authority + url.Route("DefaultApi", new { controller = controller, id = id });
}
}
There's a few other methods on there, but this is really the core of things and it works fine.
Now I want to optimize a particular page. Where previously I had two requests
Download the html
Do an Ajax query to get some data (and some links)
Now I realize that for optimization purposes it is better to do just one in this case.
Download the html with the data already JSON embedded into it.
The problem is that since the html is being generated by Mvc, I cannot create an Api UrlHelper that seems to work.
I tried
var url = new UrlHelper(new HttpRequestMessage(verb, controller.Request.Url.AbsoluteUri));
if (!url.Request.Properties.ContainsKey(HttpPropertyKeys.HttpConfigurationKey)) //http://stackoverflow.com/questions/11053598/how-to-mock-the-createresponset-extension-method-on-httprequestmessage
url.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
But this still blows up
System.ArgumentException was unhandled by user code
HResult=-2147024809
Message=A route named 'DefaultApi' could not be found in the route collection.
Parameter name: name
Source=System.Web.Http
ParamName=name
StackTrace:
at System.Web.Http.HttpRouteCollection.GetVirtualPath(HttpRequestMessage request, String name, IDictionary`2 values)
at System.Web.Http.Routing.UrlHelper.GetHttpRouteHelper(HttpRequestMessage request, String routeName, IDictionary`2 routeValues)
at System.Web.Http.Routing.UrlHelper.GetHttpRouteHelper(HttpRequestMessage request, String routeName, Object routeValues)
at System.Web.Http.Routing.UrlHelper.Route(String routeName, Object routeValues)
at MyProject.Models.ApiLinkMaker.MakeLink(String controller, String id) in w:\MyProject\Models\ApiLinkMaker.cs:line 42
...
This leads me to think that I'm going about this wrong - that I need to create the url helper from the api routing configuration somehow.
Why create one? There is an instance of the UriHelper exposed as a property on both the MVC Controller and ApiController classes.
public ActionResult Index()
{
string url = Url.RouteUrl("DefaultApi", new {httproute = "", controller = "test"});
return View();
}
Edit: Updated code. While the url helpers are different you can use the MVC url helper to resolve the web api url.
Edit2: The correct method to use if you want to get webapi routes from an Mvc UrlHelper is
string url = Url.HttpRouteUrl("DefaultApi", new {httproute = "", controller = "test"});

ASP.NET MVC route returning 404 without action

I am working on a very simple application, using MVC2 Preview 1.
I have a controller named ContentController. My problem is that /Content/Index works correctly, but /Content/ returns a 404. I am running the application on the Studio Development Server.
Tested with RouteDebugger but /Content/ returns a 404, and does not display any debugging information.
I have not changed the routing code:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
This is my controller:
public class ContentController : Controller
{
IRepository _repo = new SimpleRepository("db", SimpleRepositoryOptions.RunMigrations);
public ActionResult Index()
{
var content = _repo.GetPaged<Content>(0, 20);
return View(content);
}
It's a shot in the dark, but do you have a directory named /Content/ as well?
/Content is a controller, which is basically just a collection of actions. ASP.NET MVC needs to know WHICH action you want to run, so by leaving out the action asp.net mvc doesn't know what action to return and gives a 404.
You can tell it a default either by adding a route:
eg:
routes.MapRoute("ContentDefault", "Content", new {controller = "Content", action = "Index"});
The attributes are defined as follows:
'ContentDefault`: Name of the Route (must be unique in your routing table)
Content: The URL segment (try changing this to 'Content/Much/Longer/URL' and then go to http://localhost/Content/Much/Longer/URL to see how this works)
new {controller=.., action=...}: which controller/action combo to run for this route.
You could also override HandleUnknownAction in your controller:
protected override void HandleUnknownAction(string actionName)
{
return RedirectToAction("index");
}
Oh and incidentally, an extra piece of advice about routing.... if you add something to the route in braces { } these will be passed to the action as an attribute.
e.g. /Content/Much/Longer/Url/{page}
so the URL http://localhost/Content/Much/Longer/Url/999
will pass the 999 into your action, as the page attribute
public ActionResult Index(int Page) { }
I love MVC - never going back to WebForms - this is how web development should be!

Resources