I like to know how to configure the odata routing so that I can have
URL/odata/{databaseName}/SalesOrder
example
URL/odata/mydatabase1/SalesOrder
URL/odata/mydatabase2/SalesOrder
And then the controller to be able to retrieve the databaseName token.
I have tried to add
config.MapODataServiceRoute("odata", "databaseName", model: GetModel());
but that does not quite work.
config.MapODataServiceRoute("odata", "{companyId}/odata", model: GetModel());
Above code needed to go in to WebApiConfig and then within your controller
var company = System.Web.HttpContext.Current.Request.RequestContext.RouteData.Values["companyId"];
Related
I have created a .Net Core Web API program. I want to add a single view to it. Under the same project I add a "Views" folder. In the HomeController, where I am routing all my API requests, I created the following:
[HttpGet("view")]
public IActionResult Index()
{
return View();
}
In my Views folder I created a folder "Home" and added "Index.cshtml" to it.
When I launch the API, and navigate to "../view" I get to the return View(); line, but then it returns a 500 Internal Server Error.
This is what I don't like about the "automagical" approach of MVC convention. I have no idea where to link a view to a controller if the convention didn't work.
Update, this probably should have been my first course of action.
I added a new class to Controllers folder, and used the MVC Controller template in VS2015. I then added a view to match, and it still doesn't work automagically.
So for clarity, my project is: ASP.NET Core Web Application(.NET Core) with a Web API template. I have a "Jobs" controller class that was added at the start as 'Values' and I renamed. Then I added an MVC Controller Class named "HomeController" with the only method being "Index". I added a folder named "Views" and a subfolder named "Home", and added an MVC View Page named "Index.cshtml".
I tried to use "return View();" in the Index method, didn't work. I then tried to add [Route("Home/Index")] above the Index method. Either way, the URL will get me to my break point at "return View();" but it will never return the view.
Note : It's a little strange that you want to return a view in a Web API project, a Web API project is supposed to return some data structure, like json using return new JsonResult(your_json_here) for example.
Note 2 : you need the Microsoft.AspNetCore.Mvc framework (which is installed with the Web API template)
Anyway, you have different ways to configure routing in a asp.net core application :
Creating and extending default routes
Example of routing configuration in the Configure method :
app.UseMvc(routes =>
{
// You can add all the routes you need here
// And the default route :
routes.MapRoute(
name: "default_route",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" }
);
});
Using attributes
If you configure routing with attributes, don't forget the controller's one :
Example for the route /index :
[Route("")]
public class HomeController : Controller
{
[HttpGet]
[Route("[action]")]
public IActionResult Index()
{
return View();
}
}
Example for the route /home/index :
[Route("[controller]")]
public class HomeController : Controller
{
[HttpGet]
[Route("[action]")]
public IActionResult Index()
{
return View();
}
}
Example for the route /iputwhatiwant/actionnameiwant :
[Route("iputwhatiwant")]
public class HomeController : Controller
{
[HttpGet]
[Route("actionnameiwant")]
public IActionResult Index()
{
return View();
}
}
My screen of a .NET Core Web API project returning a view :
For more information, the official documentation is well-documented : https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing
How are you running this webapp, from the Windows commandline?... can you give us the detailed HTTP500 error. It will probably reveal something different than routing errors because that usually gives 404.
[Route("[controller]")]
public class HomeController : Controller
Note the automagical "[controller]" in the Route definition, I think its necessary now
It took me a frustratingly long while to learn the routing convention as it was being developed, but it seems to have normalized out for a few versions. Check out this tutorial documentation on the subject in MVC: Attribute Routing in ASP.NET MVC 5, which is MVC not WebCoreAPI where it is likely based from. If you have a better documentation specific to Web Core API, use that.
This ASP.NET Web Core Build a web API tutorial documentation has some good points about what you seem to be trying to do. Specifically, the section title "Getting to-do items" has this code:
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(long id)
{
var item = _todoRepository.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
Looking at that with benefit of some measure of MVC routing experience, it looks particularly different from your approach in that the HTTP verb annotation member property value used is a query parameter.
Seeing I am guessing using known inexpertise, still, I think you need to get the attribute routing fixed, and maybe return an ObjectResult instead of a view, as NightOwl888 suggests. The server error might also have much more useful information along with the exception message.
EDIT: Sorry, I may have misunderstood your question. If you are trying to build an app that serves dynamic web pages instead of a WebAPI that serves data object results, this Build an MVC Web App tutorial, similar to the "Build a web API" tutorial I mentioned before might have your app structure problem answer. If you are trying to do both, you should probably start with the MVC Web App structure or use two separate projects.
The (only) way I have got this working is to declare the path as an attribute on the action - in the same way you have done but with the format as below (Controller/Action):
[HttpGet("Home/Index")]
public IActionResult Index()
{
return View();
}
I was missing:
"preserveCompilationContext": true
in the build options of my project.json
I'm trying to create a REST api based on the Asp.Net MVC4 web api framework. The GET requests are working just fine. All other verbs are getting ignored by the server.
It just says the following:
"No action was found on the controller 'Track' that matches the request."
Though the example error is from the Track controller all other controllers have the same problem.
This is the method on the controller Track I'm trying to call:
[HttpPost]
public Object Index(string token, string juke, string track)
{
}
I'v tried it using a JSON object like so:
{ "track": "0000", "juke": "0000" }
And I tried to use the "normal" way:
track=0000&juke=0000
The '0000' in the examples above are stand-ins for the real id's.
To be sure I'm also posting the Register() from WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
config.Routes.MapHttpRoute(
name: "DefaultIndexBackEnd",
routeTemplate: "back-end/{controller}/{token}",
defaults: new { action = "Index", token = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultBackEnd",
routeTemplate: "back-end/{controller}/{action}/{token}",
defaults: new { token = RouteParameter.Optional }
);
}
Try this in your TrackController. Because you are using multiple parameters, they must be declared as optional.
[HttpPost]
public Object Index(string token="", string juke="", string track="")
{
}
You can make parameter token mandatory because token is declared as optional in routing configuration DefaultIndexBackEnd. I think using [FromBody] attribute is a good idea when there is more than one parameter for POST actions.
First, it's important to understand how a typical REST Web API is supposed to work. Typically, it uses different HTTP verbs (GET, POST, PUT, DELETE) for specific actions.
GET: get an entity (or a collection) from the server
POST: create a new entity
PUT: update an existing entity
DELETE: delete an existing entity
So when I see [HttpPost] on your Index action, it seems to me that the REST API pattern is broken.
Instead, in your controller you should have a Entity Get(int id) action (to get data) and a void Post(Entity entity) action to create new records.
No need to decorate your actions with HttpGet or HttpPost, the MVC Api framework will route the request to your action based on their names.
You can take a look at an example here.
After several hours of trying and researching articles I finally found an article that precisely described my problem! If you're having the same problems, check out the article.
The problem was that I had to use the [FromBody] attribute on one parameter of the of the action. After moving juke and track into a model it finally worked as I had hoped.
Thanks everyone for the help, you all set me on the right track!
I am trying to implement a method for registering a user in my OData based asp.net Web API.
The ploblem is i would like to have it on the root url followed by /Register.
The register action itself makes use of a RegisterModel which contains the right information to create the user.
I have tried to add a custom action in the WebApiConfig. Problem with this is that OData then expects a simple parameter and sending whole models over won't succeed.
Simple action specification like below won't work for me. The endpoint can be found but the model is always 'null'.
var actionRegister = builder.Action("Register");
actionRegister.Parameter<RegisterModel>("model");
actionRegister.Returns<IdentityResult>();
The API method is started as follows:
[AllowAnonymous]
[HttpPost]
[ODataRoute("Register")]
public async Task<IHttpActionResult> Register(RegisterModel model)
{
Any help is welcome. My ultimate goal would be to have a controller call in my user controller that can register users via the route /Register.
Please take a look at the http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v4/ODataActionsSample/ODataActionsSample/ sample code here, the unbound function should meet your needs.
I have an existing .NET 4 console application which I want to start exposing a REST API. I'm using the Microsoft self host Web API library to have it expose that API, but I'm having trouble understanding how the routing path gets developed.
Here is an example of a controller, which should expose some database objects my console application already handles:
public class UserController : ApiController
{
UserInformation[] users;
public IEnumerable<UserInformation> GetAllUsers()
{
// snip.
}
public UserInformation GetUserById(int id)
{
// snip.
}
}
And I'm exposing my API in Program.cs like so:
var config = new HttpSelfHostConfiguration("http://localhost:8800");
config.Routes.MapHttpRoute(
"API Default", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
using (var server = new HttpSelfHostServer(config)) { // code }
Given the above code, I'd expect that I could get resources by making http requests like http://localhost:8800/api/users and http://localhost:8800/api/users/1, but those don't seem to work. How does the controller part of the GET request get created? It doesn't seem like users is the correct routing path for the API, but I'm not sure what goes there.
Thanks for any help
That's because your controller is called UserController and not UsersController. Either rename your controller to UsersController or modify your request to go to http://localhost:8800/api/user.
This should solve the problem.
I have been playing with Webapi 2.0 and OData 2.0 for past 2 weeks. I would like to know as to when to use OData routing and Webapi Attribute routing.
Thanks,
Pavan
Web API is a general framework for creating HTTP endpoints (web APIs/REST APIs). You can also use it to create OData endpoints, which is a more specific application of ASP.NET Web API.
So the first question is whether you want to create an OData endpoint or some other type of REST API.
If you are creating an OData endpoint, use OData routing. Otherwise use the "regular" Web API routing
Web API Routing
you can use default routing but if you want to defined your route templates then you can used AtrributeRouting which is using convention-based routing
In this type of routing, you define one or more route templates, which are basically parameterized strings.
When the framework receives a request, it matches the URI against the route template
install following nuget package :
"Install-Package Microsoft.AspNet.WebApi.WebHost"
Add following line in your "WebApiConfig.cs" file
config.MapHttpAttributeRoutes();
create your webapicontroller like following
[Route("api/users")]
public HttpResponseMessage GetUsers(int userId)
{
you can access your web api like this URL:
http://localhost:8080/api/users/
Web API Odata Routing
when you want to use IQueryable instead of IEnumerable then you can use odata
install nuget package for odata
"Microsoft.AspNet.WebApi.OData"
Add following code in your "WebApiConfig.cs" file
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<ViewTest>("TestOdata");
var model = modelBuilder.GetEdmModel();
config.Routes.MapODataRoute(routeName: "OData", routePrefix: "odata", model: model);
Add following code in your "UsersOdataController.cs" file
public class TestOdataController : OdataController
{
//GET odata/TestOdata
public IQueryable<ViewTest> Get()
{
try
{
return context.View_TestRepository.GetQueryable();
}
catch (Exception ex)
{
throw ex;
}
}
}
ViewTest : view model class with your required columns
View_TestRepository : Repository class
you can access your odata web api by following URL:
"http://localhost:8080/odata/TestOdata"