ApiController within an area - asp.net-web-api

I want to have BlaController : ApiController, with BlaController located in /Areas/XXX/ ( or namespace MySolution.Areas.XXX.Controllers )
The problem is that when I browse to http://localhost:1935/XXX/Bla/SomeAction I get 404.
Normal controllers (: Controller) do not throw 404.
Note: SomeAction would be for example "public string SomeAction() { return "hi"; }", within BlaController
*Note 2: Tried* http://localhost:1935/api/Bla/SomeAction and didn't work either

Based on this SO question, looks like you need to build your own HttpControllerFactory in order to support Areas with WebAPI.
The question references an article on how to do this: http://netmvc.blogspot.com/2012/03/aspnet-mvc-4-webapi-support-areas-in.html
Hope this helps.
UPDATE:
Thanks to Bertrand who pointed to an updated article about WebApi support for Areas (which is still doesn't have by default). The updated link is http://netmvc.blogspot.be/2012/06/aspnet-mvc-4-webapi-support-areas-in.html

Related

How to use higher version for web api controller

I am following below:
https://www.hanselman.com/blog/ASPNETCoreRESTfulWebAPIVersioningMadeEasy.aspx
Is it possible to have directly higher version for a web api controller.
like:
ApiVersion("2.05")]
[RoutePrefix("api/v{version:apiVersion}/ger")]
public class caGerController
[Route("~/api/ger/getDetail")]
[Route("getDetail")]
GetGerData
when using above one, it only works when using URL as api/v2.05/ger/getDetail
But It fails working while using URL as api/ger/getDetail and getting message as "Code": "ApiVersionUnspecified",
If change version from 2.05 to 1.0 (as all other controller) then api/ger/getDetail works.
How to solve this, I need 2.05 for this controller and need to access api/ger/getDetail URL as well.
Thanks
Since you are versioning by URL segment, you'll have to do a few things. First in the options, you need to allow implicit versioning using:
options.AssumeDefaultVersionWhenUnspecified = true;
Your original API had some version that was never declared or named. The default configuration will use "1.0". If you want the default to be something else, specify:
options.DefaultApiVersion = new ApiVersion( 2, 0 );
The next step is that you have to float the route template on the controller that you want to have the default path. ASP.NET and all other stacks I know do not have a way to provide or fill-in default values in the middle of the route template.
If "2.0" is your initial, default version, then your controller will look like:
[ApiVersion( "2.0" )]
[ApiVersion( "2.05" )]
[RoutePrefix( "api" )]
public class GerController : ApiController
{
[Route( "ger/getDetails" )]
[Route( "v{version:apiVersion}/ger/getDetails" )]
public IHttpActionResult GetDetails() => Ok();
}
If you change the controller that maps to the default route, you have to move the route template to that new controller type.
This is an unfortunate consequence of versioning by URL segment. If you don't change the default route mapping, then it shouldn't be a big deal to manage; otherwise, you should consider disallowing implicit versioning or elect an alternate versioning method.
For more information, please refer to this wiki topic.

.net core mvc routing and controllers

So I am brand new to .net. I am learning .net core right now. I am trying to figure out routing. I can not seem to get the routing to look in any folder except Home and Shared. I have looked all over the internet and tried many things. There seems to be something I am missing. Here is what I got
app.UseMvc(routes =>
{
routes.MapRoute(
name: "test",
template: "Register/test",
defaults: new { controller = "Register", action = "test"}
);
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
I have a Register folder with a test.cshtml file in just to try t figure this routing out. And this is is in my HomeController.cs file
public IActionResult test()
{
return View();
}
on my _Layout page I have this link
<li><a asp-area="" asp-controller="Register" asp-action="test">Test</a></li>
It works fine when I put it in the home folder, but I want to keep things separate. I know there is something I am missing. I've poured through all kinds on articles online including Stack Overflow, and I just don't understand what I am missing. From what I read its suppose to be like the Parent folder/File/ then and id that may be attached to that like a user name I have tried other formats for the routing with no luck, this was just my most recent attempt. I just can't help but think I need some bit of code somewhere else.
From your question it looks like you have the following code in your HomeController.
public IActionResult test()
{
return View();
}
That actually belongs in your RegisterController because the route template you defined is an explicit capture with defaults to the "Register" controller and the "test" action.
The view called "test.cshtml" - which should be named as such because of the default convention - should reside in your \Views\Register folder, next door to \Views\Home.
There are a couple of reasons why this may have worked in some fashion. First, the view is discoverable for any controller if it's in shared. Without knowing more about the requests you tried, it's difficult to determine if routing kicked in on the first route or second, but if that method was truly on HomeController requests to /home/test would have worked.
It looks to me like you're exploring routing. That is great - I 100% encourage the experimentation - so long as you know that routing isn't necessarily the lowest hanging fruit to learn. It's also something that you shouldn't have to touch 93.7% of the time. For example, the route you have defined about wouldn't be required for the controller and action you're adding with RegisterController and test.
Cheers.

How to add breadcrumb to Spring MVC?

How can I add breadcrumb to all pages of Spring MVC? I suppose it would be a good question to ask as breadcrumbs are quite popular now and it might be the question of many others.
I've found this solution that is using dummiesmind.breadcrumb.springmvc.annotations, there is also a question on stackoverflow but I could not learn much except finding similar solution to the one that Ive found. Another solution is this one that is using JavaScript.
Does anyone have a better option to the ones I mentioned?
#Link(label="Sample Link", family="controllerFamily", parent="");
#RequestMapping(value = "sample.do", method=RequestMethod.GET);
public ModelAndView sampleMethod(HttpSession session){...}
What are you using to display your pages ? JSP ? Thymeleaf ?
The link you point to seems a good option or at least you can build something custom that works for you based on that. Using annotations keeps your code clean but you need to make sure you add them everywhere.
You could use an abstract controller where you define a method to create a ModelAndView object for all pages. You could add breadcrumbs that way :
protected ModelAndView createModelAndView(String pageName, BreadCrumb breadCrumb) {
ModelAndView modelAndView = new ModelAndView(pageName);
modelAndView.addObject("breadCrumb", breadCrumb);
return modelAndView;
}
Of course you would need to call that method everytime in your implementation.
One usage of this would be to pass your request url as parameter and parse it to build breadcrumbs by associating text to each part of the path (using the current local to tanslate it). So for example "/admin/user/list" would give you Home >> Administration >> User management >> List of users. That should be easy to build.

Routing document-relative static urls in MVC3

I'm integrating a JavaScript library into an ASP.NET MVC3 web app. The library assumes it will be installed next to the page that references it, and so it uses document-relative URLs to find its components.
For example, the default directory layout looks like
container-page.html
jslibrary/
library.js
images/
icon.png
extensions/
extension.js
extension-icon.png
However, I want to reference the library from the view in /Home/edit. I install the library in the default Scripts\jslibrary\ When I reference the library in the view in Views\Home\edit.cshtml, the library's document-relative links like
images/icon.png
end up as requests to
http://localhost/Home/images/icon.png
which results in a File Not Found (404) error. How do I construct a route to look for
{anyControllerName}/images/{anyRemainingPathInfo}
and serve up
http://localhost/Scripts/jslibrary/images/{anyRemainingPathInfo}
?
(full disclosure: I'm still on IIS 6 in Production, and not much chance of going to IIS7 any time soon, so if this is better done at the IIS level, please account for IIS6. Thanks!)
You could create a controller for handling you redirect logic - for example an "Images"controller. Register a global route in your Global.asax file, using the pattern (more on this type of pattern here:
routes.MapRoute(
"Images", // Route name
"{xyz}/{controller}/{path}", // URL with parameters
new {controller = "Images", action = "Index", path= UrlParameter.Optional} // Parameter defaults);
In your controller:
public ActionResult Index(string path)
{
//format path, parse request segments, or do other work needed to Id file to return...
return base.File(path, "image/jpeg"); //once you have the path pointing to the right place...
}
Not sure if this solution will work for you, wish I could come up with something more elegant. Best of Luck!
Short of rewriting the library and having it check for the appropriate directory the only solution I can think of is to include the views, library and supporting files in a directory structure that the library can access. This of course would break MVC's convention over configuration way of finding views, so you would have to write a custom override of the way Razor looks for views, which is not too complex to do, but you might be making life more difficult for yourself down the road depending on your application. Your call which is the lesser of the two evils :) (I'd go for fixing the library)
Make a help function
#functions{
public string AbsoluteUrl(string relativeContentPath)
{
Uri contextUri = HttpContext.Current.Request.Url;
var baseUri = string.Format("{0}://{1}{2}", contextUri.Scheme,
contextUri.Host, contextUri.Port == 80 ? string.Empty : ":" + contextUri.Port);
return string.Format("{0}{1}", baseUri, VirtualPathUtility.ToAbsolute(relativeContentPath));
}
}
Calling
#AbsoluteUrl("~/Images/myImage.jpg") <!-- gives the full path like: http://localhost:54334/Images/myImage.jpg -->
This example are from
https://dejanvasic.wordpress.com/2013/03/26/generating-full-content-url-in-mvc/

Weird behaviour of RedirectToAction

I'm developing portal in MVC 3. Have controller (MyController) with three methods Add (get and post verssion) and Index and part of add method looks like:
[HttpPost]
public virtual RedirectToRouteResult AddItem(Item item)
{
(...)
return RedirectToAction("Index");
}
Simple? Not fot me:)
Item is added properly and when redirecting comes url looks like:
MyController/Index
and not:
mySite/MyController/Index
and of course that is bad news. This situation happens only in one case in one place in the whole portal. What's wrong?
What you get as a return is a relative path, relative to your current path.
Problem solved-i had to change order of routemaps in global.asax -request was catched by wrong map.

Resources