ASP.NET MVC 4 and Web API And Overloads - asp.net-mvc-4

I'm new to ASP.NET MVC 4. I've created an endpoint. That endpoint is available at:
/myController/actionName
In my controller, I have the following defined:
[HttpPost]
public void ActionName(string parameter1)
{
}
I am trying to figure out if its possible to have overloads. In ASP.NET MVC 4 Web API, is there a way for me to say something like the following:
[HttpPost]
public void ActionName(string parameter1)
{
}
[HttpPost]
public void ActionName(string parameter1, string parameter2)
{
}
If not, is there a way to make parameters optional?
Thank you!

You cannot overload controller actions, however, you can specify a parameter to be optional when defining your routing as follows:
routes.MapRoute(
name: "OptionalParameter",
url: "myController/actionName/{parameter1}/{parameter2}",
defaults: new { controller = "myController", action = "actionName", parameter1 = "Default Value", parameter2 = UrlParameter.Optional }
);

Related

How to use DataTokens in ASP.NET Core 3.1 when performing dynamic routing?

I am using the class DynamicRouteValueTransformer built into ASP.NET Core 3.1 to perform dynamic controller routing as demonstrated in the code below.
public class UrlRouteTransformer : DynamicRouteValueTransformer
{
public override ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values)
{
var controller = "home";
var action = "index";
//Make decision here on which controller and action to call. i.e call the database etc
values["controller"] = controller;
values["action"] = action;
return new ValueTask<RouteValueDictionary>(values);
}
}
This code is working as expected, but I want to know how you would set data tokens?

WCF REST - parameterless GET not working

I'm trying to get the most basic operation working for my WCF restful service going.
I have a service on my local machine. Let's call it TeskService:
http://localhost:52309/Services/TaskService.svc
On the back end, I have a WebGet:
[ServiceContract]
public interface ITaskService
{
[WebGet]
void CreateTask();
}
If I type the following into my browser, nothing gets triggered (I get a 404):
http://localhost:52309/Services/TaskService.svc/CreateTask
If I change my definition to accept a parameter:
[WebGet(UriTemplate="CreateTask/*")]
void CreateTask();
And then pass in any value:
http://localhost:52309/Services/TaskService.svc/CreateTask/randomText
Then the method triggers.
I don't want to pass in anything. I just want the method to fire. What am I doing incorrectly?
According to this link:
http://msdn.microsoft.com/en-us/library/bb412172(v=vs.110).aspx
they have
[ServiceContract]
interface ICustomer
{
//"View It"
[WebGet]
Customer GetCustomer():
}
and calling it using /GetCustomer should be fine.
Ideas? Thoughts? Inspiration?
This is proving to be more difficult for me than it should be.
EDIT:
Could it be affected by my MVC routing in the same project?
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
If you use [WebGet]
[ServiceContract]
public interface ITaskService
{
[WebGet]
void CreateTask();
}
then you can call using http://localhost:52309/Services/TaskService.svc/CreateTask.
If you use [WebGet(UriTemplate="")]
[ServiceContract]
public interface ITaskService
{
[WebGet(UriTemplate="")]
void CreateTask();
}
then you can call using http://localhost:52309/Services/TaskService.svc.

Routing GET and POST routes in ASP.NET MVC 4

I am trying to setup a Login form in an ASP.NET MVC 4 app. Currently, I have configured my view as shown here:
RouteConfig.cs
routes.MapRoute(
"DesktopLogin",
"{controller}/account/login",
new { controller = "My", action = "Login" }
);
MyController.cs
public ActionResult Login()
{
return View("~/Views/Account/Login.cshtml");
}
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model)
{
return View("~/Views/Account/Login.cshtml");
}
When I attempt to visit /account/login in the browser, I receive an error that says:
The current request for action 'Login' on controller type 'MyController' is ambiguous between the following action methods:
System.Web.Mvc.ActionResult Login() on type MyApp.Web.Controllers.MyController
System.Web.Mvc.ActionResult Login(MyApp.Web.Models.LoginModel) on type MyApp.Web.Controllers.MyController
How do I setup a basic form in ASP.NET MVC 4? I've looked at the sample Internet App template in ASP.NET MVC 4. However, I can't seem to figure out how the routing is wired up. Thank you so much for your help.
I haven't tried this yet but can you try annotating your Login actions with the appropriate Http Verb - I'm assuming that you're using a GET for viewing the login page and a POST for processing the login.
By adding [HttpGet] for the first action and [HttpPost] for the second action the theory is that ASP.Net's routing will then know which Action method to call based upon which method has been used. Your code should then look something like this:
[HttpGet] // for viewing the login page
[ViewSettings(Minify = true)]
public ActionResult Login()
{
return View("~/Views/Account/Login.cshtml");
}
[HttpPost] // For processing the login
[ViewSettings(Minify = true)]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model)
{
return View("~/Views/Account/Login.cshtml");
}
If this doesn't work, consider having two routes and two differently named actions like below:
routes.MapRoute(
"DesktopLogin",
"{controller}/account/login",
new { controller = "My", action = "Login" }
);
routes.MapRoute(
"DesktopLogin",
"{controller}/account/login/do",
new { controller = "My", action = "ProcessLogin" }
);
There are other similar questions and answers on StackOverflow already, take a look at: How to route GET and DELETE for the same url and there is also the ASP.Net documentation which might also help.

Have Microsoft changed how ASP.NET MVC deals with duplicate action method names?

I might be missing something here, but in ASP.NET MVC 4, I can't get the following to work.
Given the following controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(string order1, string order2)
{
return null;
}
}
and it's view:
#{
ViewBag.Title = "Home";
}
#using (Html.BeginForm())
{
#Html.TextBox("order1")<br />
#Html.TextBox("order2")
<input type="submit" value="Save"/>
}
When start the app, all I get is this:
The current request for action 'Index' on controller type
'HomeController' is ambiguous between the following action methods:
System.Web.Mvc.ActionResult Index() on type
ViewData.Controllers.HomeController System.Web.Mvc.ActionResult
Index(System.String, System.String) on type
ViewData.Controllers.HomeController
Now, in ASP.NET MVC 3 the above works fine, I just tried it, so what's changed in ASP.NET MVC 4 to break this?
OK there could be a chance that I'm doing something silly here, and not noticing it.
EDIT:
I notice that in the MVC 4 app, the Global.asax.cs file did not contain this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
which the MVC 3 app does, by default. So I added the above to the MVC 4 app but it fails with the same error. Note that the MVC 3 app does work fine with the above route. I'm passing the "order" data via the Request.Form.
EDIT:
In the file RouteConfig.cs I can see RegisterRoutes is executed, with the following default route:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
I still get the original error, regards ambiguity between which Index() method to call.
Because MVC4 ships with ASP.Net Web.API you can potentially reference two HttpPostAttribute (the same applies to the other attributes like HttpGet, etc.):
System.Web.Mvc.HttpPostAttribute is used by ASP.Net MVC so you need to use it on actions inside Controller derived controllers
System.Web.Http.HttpPostAttribute is used by ASP.Net Web.API so you need to use it on actions inside
ApiController derived controllers
You have acidentally referenced System.Web.Http.HttpPostAttribute in your code. Change it to use the right attribute and it should work correctly:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[System.Web.Mvc.HttpPost]
public ActionResult Index(string order1, string order2)
{
return null;
}
}

Trouble getting a response from an asp.NET WebAPI in an Area

I'm trying to add a ASP.NET Web API ( from MVC 4 ) to my project..... But I'm having some trouble getting any response from the Area/WebAPI/Controller ( not quite sure where it's going wrong...)
I installed the Route Debugger, and if I go to my main page... I see the routes...
Matches Current Request Url Defaults Constraints DataTokens
False api/{controller}/{action}/{id} action = Index, id = UrlParameter.Optional (empty) Namespaces = OutpostBusinessWeb.Areas.api.*, area = api, UseNamespaceFallback = False
False {resource}.axd/{*pathInfo} (null) (empty) (null)
True {controller}/{action}/{id} controller = Home, action = Index, id = UrlParameter.Optional (empty) (empty)
True {*catchall} (null) (null) (null)
So it seems like the route is setup
Next I have a PlansController in the "api" Area, It's just the default apiController generated by "Add New"...
public class PlansController : ApiController
{
// GET /api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET /api/<controller>/5
public string Get(int id)
{
return "value";
}
// POST /api/<controller>
public void Post(string value)
{
}
// PUT /api/<controller>/5
public void Put(int id, string value)
{
}
// DELETE /api/<controller>/5
public void Delete(int id)
{
}
}
Now When I go to http://localhost:2307/api/Plans/1
I get
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /api/Plans/1
Any ideas why? Is there something I need to configure?
ASP.NET MVC 4 doesn't support WebApi in areas out of the box.
Martin Devillers proposed a solution: ASP.NET MVC 4 RC: Getting WebApi and Areas to play nicely
You can also have more details in my response on a similar question (especially for support with portable areas):
ASP.Net WebAPI area support
Change it to:
// GET /api/<controller>
public IEnumerable<string> GetMultiple(int id)
{
return new string[] { "value1", "value2" };
}
Call it with:
http://localhost:2307/api/Plans/GetMultiple/1
This is my Global.asax:
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
My Controller:
public class MyApiController : ApiController
{
public IQueryable<MyEntityDto> Lookup(string id) {
..
}
I called it as follows:
http://localhost/MyWebsite/api/MyApi/Lookup/hello
Works perfectly.