I am using the latest Angular template plus ASP.Net Core WebApi projects in VS 2022. I am trying to convert for my use by renaming the WeatherForecastController. I find that WeatherForecastPlop2Controller works fine, but BobWeatherForecastController does not work.
I have been playing for last whole two days trying to get multiple controllers working with the sample projects. I can see them working via Swagger with API port, but for some reason only the WeatherForecastController calls work via the proxy.
I am new to web development so any pointers would be much appreciated.
Thanks
You can try to replace [Route("[controller]")] to [Route("WeatherForecast")] in BobWeatherForecastController.
[ApiController]
[Route("WeatherForecast")]
public class BobWeatherForecastController: ControllerBase
{
}
So that the routing of BobWeatherForecastController is still WeatherForecast/....
I discovered that the problem was with the proxy.conf.js file;
const PROXY_CONFIG = [
{
context: ["/weatherforecast", ],
target: "https://localhost:7085",
secure: false
}
]
module.exports = PROXY_CONFIG;
The proxy middleware seems to not care what comes after the context. Which is why WeatherForecastPlop2Controller works but BobWeatherForecastController does not. So to get the renamed Controller to work in my Angular app I needed to match the new name in this proxy file.
Related
I'm working on a web service using spring-boot-starter-jersey and spring-boot-starter-tomcat (v. 1.5.2) and as such, I'd rather not add spring-boot-starter-web and further complicate my configuration. I want to stick the Swagger UI static files in a folder and serve them from there.
What I'm wondering is, can I serve static files using just spring-boot-starter-tomcat? I've found Spring documentation saying that I can server static content from a variety of sources on the classpath, but the examples I've found seem to require Spring MVC. I've tried disabling Jersey and putting static files in src/main/resources/static to test just Tomcat, but when I go to localhost/index.html, I get a 404 not found error.
As you might be able to tell from my path, I'm using Maven.
Since you can serve static files with just Tomcat, it seems like I should be able to serve static files with spring-boot-starter-tomcat. If this is the case, where do I put those files?
To put this another way, say I have started with the Spring-provided
spring-boot-sample-jersey project. I have a requirement that the Jersey web service answer calls to the root address (/). How would I add some static content (HTML, CSS, JS) to be served from subdirectory called /swagger?
So the default servlet (which serves static content) is by default registered. But it will use only search specific paths as the document root. I had to go digging through source code to finally find it. If you look in the AbstractEmbeddedServletContainerFactory, you'll see
private static final String[] COMMON_DOC_ROOTS = {
"src/main/webapp", "public", "static" };
If we don't explicitly set the document root, the above three are the paths that will be searched. In order, the first directory found that exists, will be used as the document root. I've verified that all of these work.
If you want to set a different directory, you can use a customizer bean
#Bean
public EmbeddedServletContainerCustomizer tomcatCustomizer() {
return new EmbeddedServletContainerCustomizer() {
#Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setDocumentRoot(new File("src/main/resources/static"));
}
};
}
The one thing I haven't figured out is if we can serve files as classpath resources, instead of file system resources. If you look at the source code I linked to, it has some code that looks for the existence of a META-INF/resources. I thought that might work, but unfortunately it didn't for me. Maybe some guys of the Spring Boot team can enlighten us.
Right now I'm developing an ASP.Net Web API and using Swashbuckle for its documentation.
I know that Swashbuckle use Swagger-UI internally, I know that we can modify the layout by injecting our css or javascript file, even change the layout of index.html.
I found a good themes for Swagger-UI https://github.com/jensoleg/swagger-ui and trying to implement it but can't make it works. Especially when I want to inject bootstrap.js. Is there anyway I can completely change Swashbuckle Swagger UI implementation so I can use the solution from that repo?
Sure you can - in two steps.
1) Include file Index.html as Embedded resource in your assembly. For example let's say your web api project is named "Contosco.Api" and Index.html will be located under "/Content/Index.html" in this project.
2) Override swagger UI main html page with your own
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration.EnableSwagger(c => {
// configure swagger
})
.EnableSwaggerUi(c => {
// beware - the Contosco.Api.Content.Index.html has to match your project paths :)
c.CustomAsset("index", thisAssembly, "Contosco.Api.Content.Index.html");
});
}
}
For .NET Core projects the solution differs a bit from the (correct) answer of #OndrejSvejdar:
After adding index.html as an embedded resource, you have to add the following line to app.UseSwaggerUI() in your Startup.cs...
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
app.UseSwaggerUI(c =>
{
c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("Your.Default.Namespace.Subfolder.Swagger_Custom_index.html");
});
//...
}
All details of the process can be found here: https://stackoverflow.com/a/51043251/430742
You just download .zip folder, extract and include to your project.
In SwaggerConfigre.cs you don't need configure any more.
Just put template into folder Swagger and when you access {domain}/swagger it will hit index.html. (Don't need change Build action to Embedded Resource, Content is fine)
I was able to use the latest swagger-ui by following the simple steps here ,https://swagger.io/docs/swagger-tools/#swagger-ui-documentation-29
Download the swagger-ui from GitHub
Extract and copy the dist (rename folder to swagger) folder and include it in the project
Modify index.html in the dist folder to point to your swagger doc path (which off course is generated by Swashbuckle)
Started writing a simple filter to pull some stuff from request on each action load, copied some code from other stackoverflows that looks like so:
public class TestKeyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext context)
{
if (context.Request.Properties.ContainsKey("test"))
{
// do stuff
}
}
}
Then added the attribute with the rest:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
GlobalConfiguration.Configuration.Filters.Add(new ElmahHandledErrorLoggerFilter());
filters.Add(new HandleErrorAttribute());
filters.Add(new TestKeyAttribute());
}
On run, results in this error:
The given filter instance must implement one or more of the following filter
interfaces: IAuthorizationFilter, IActionFilter, IResultFilter, IExceptionFilter.
Most of the links I've found relate to MVC 3, and this seems to work; I am however using MVC 4 and using Web API - is there some other way I need to register the attribute now?
Just a note: I don't want the filter attached to Web API controllers (adding it to GlobalConfiguration.Configuration.Filters does work, though), but rather the normal web controllers.
Edit: I know I can get this working by inheriting from IActionFilter instead and using OnActionExecuting, I'm just curious why this approach doesn't work, since a bunch of tutorials seem to say it should.
I had the same error and was puzzled as ElmahHandledErrorLoggerFilter does implement IExceptionFilter.
After investigation, I kicked myself, I'd added the filters.Add(new ElmahHandledErrorLoggerFilter()); to the MVC site config under the FilterConfig class. Adding config.Filters.Add(new ElmahHandleErrorApiAttribute()); instead to the WebApiConfig class works.
Note: I'm using WebAPi v1 here but I've configured a v2 project in the same way.
The reason this doesn't work is that your filter is a WebAPI filter, which is not interchangeable with Mvc filters. The Mvc and WebAPI FilterAttribute and related classes and interfaces have many of the same names (which is why the tutorials appear to say this should work), but they live in different namespaces. Mvc filter classes live in System.Web.Mvc and WebAPI classes live in System.Web.Http.
Further reading here: https://stackoverflow.com/a/23094418/22392
When using MVC4, the project where your custom attribute resides must contain a reference to the System.Web.Http.Common library. I added it to my project using NuGet and hey presto! the error goes away.
I have a webforms application (VB.net, .NET 4.0) which is translated in three languages and I managed to localize everything except the URLs. My preference is to use routing, so I'd like to find a solution in this direction (not URL rewriting or IIS rewrites, etc.)
Out of many read articles I stumbled into this one as well: http://blog.maartenballiauw.be/post/2010/01/26/Translating-routes-%28ASPNET-MVC-and-Webforms%29.aspx, but this example is for MVC application. (As are the most of the questions here as well)
Any comments and ideas are very much welcome!
I could implement Maarten's solution in a WebForms ASP.NET application as described below.
I downloaded his sample and opened with Visual Studio. As you see it the essential part of translated routing can be found in Routing folder.
I created a new Class Library project in my web application, and copied these 5 files. This project missed some assembly references, so I added System.Web and System.Web.Routing to it.
After this there was only one problem in TranslatedRouteCollectionExtensions class. The two extension methods used MvcRouteHandler. This is the only piece of code which depends on MVC. To eliminate this dependency modify both extension methods like this:
public static TranslatedRoute MapTranslatedRoute(
this RouteCollection routes,
string name,
string url,
object defaults,
object routeValueTranslationProviders,
IRouteHandler routeHandler,
bool setDetectedCulture)
{
TranslatedRoute route = new TranslatedRoute(
url,
new RouteValueDictionary(defaults),
new RouteValueDictionary(routeValueTranslationProviders),
setDetectedCulture,
routeHandler);
routes.Add(name, route);
return route;
}
I added a reference in my Web Application to this Class Library project.
With this modification Maarten's example of register a translated route changes as follows:
routes.MapTranslatedRoute(
"TranslatedRoute",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" },
new { controller = translationProvider, action = translationProvider },
new GeneralRouteHandler(),
true
);
Implementing a custom route handler is not a complicated process. You can find many good articles about it.
I've just installed Visual Studio 2010 and have created a new MVC2 project so that I can learn about the changes and updates and have discovered an issue with areas that I'm not sure what to make of.
I created a new EMPTY MVC2 project
I right clicked the project and, from the context menu, added a new area called "Test"
In the new test area, I added a controller called "Data".
The code is:
public class DataController : Controller
{
//
// GET: /Test/Data/
public ActionResult Index()
{
Response.Write("Hi");
return new EmptyResult();
}
}
Now, I compile and call this address:
http://localhost/mytest/test/data and get the output:
Hi
All good. Now I call this: http://localhost/mytest/data and get the same response! I thought routing was supposed to take care of this? Am I overlooking something? Or has the default project setup for MVC2 overlooked something?
This is intentional. The default route in Global.asax does not limit its search to a particular area or set of namespaces. There are overloads of MapRoute (see one example on MSDN) which take a namespaces parameter, which can be used to disambiguate which controller was meant by this request. But even so, the namespaces parameter is just a hint about which namespaces to search in first; it's not a restriction.
In short, in MVC, you have to be prepared for any of your controllers to be hit by any route. This is why all of the MVC documentation states that security and other logic should be done at the controller level, never at the route level.