Disable all server routing except for api calls in asp.net - asp.net

I have created a angular2 project using ASP.net with webapi. I have everything setup correctly and working but when I am routing in angular2 such as: "localhost:1234/login" the source of the page is displaying the error:
HTTP Error 404.0 - Not Found
This is obviously because of server routing that cant find any path for this. My question is: Is there any way to disable all routing by the server except for if I'm doing a call like: "localhost:1234/api/login" because that would entail making a server request to a webapi controller which will return JSON. I want angular2 to handle all forms of routing. And the server just to handle data being pushed out.
Thank you in advance

If Angular is generating views by consuming APIs this should not be an issue. If the server is expected to serve up HTML for the routes Angular is calling then it needs equivalent routing configured.

Yes you can do this in your startup.cs class.
You need to configure the way your API calls are made in a way, and redirect to your index.html otherwise like so :
app.UseMvc(r =>
{
r.MapRoute(
name: "default",
template: "{controller}/{path?}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" }
);
r.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" }
);
});

Related

What is difference between setting up routing in asp.net core mvc project with app.UseMvc() or app.UseEndpoints?

I know that when migrating from asp.net 2.2 to 3 app.UseMvc() line in startup.cs file's configure method is replaced by app.UseRouting(); app.UseAuthorization(); app.UseEndpoints();.
Can anyone explain how app.UseEndpoints() and app.UseMvc() works internally ?
Under the asp.net core mvc 2.2 framework, to use traditional routing, you must configure the IRouteBuilder interface in the UseMVC middleware.
In the Configure method of the application Startup, the default routing settings are as follows:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
{
In the call to UseMvc, MapRoute is used to create a single route, also known as the default route. Most MVC applications use routing with templates. A convenient method for the default route can be used:
app.UseMvcWithDefaultRoute();
UseMvc and UseMvcWithDefaultRoute can add an instance of RouterMiddleware to the middleware pipeline. MVC does not directly interact with middleware, but uses routing to process requests. MVC connects to the route through an instance of MvcRouteHandler.
     UseMvc does not directly define any routes. It adds placeholders {controller=Home}/{action=Index}/{id?} to the route collection of attribute routing. By overloading UseMvc(Action), users are allowed to add their own routes, and attribute routing is also supported.
UseEndpoints: Perform matching endpoints.
It separates routing matching and resolution functions from endpoint execution functions, and until now, these functions are bundled with MVC middleware.
First of all,you could have a look at their source code:
public static IApplicationBuilder UseEndpoints(this IApplicationBuilder builder, Action<IEndpointRouteBuilder> configure)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}
VerifyRoutingServicesAreRegistered(builder);
VerifyEndpointRoutingMiddlewareIsRegistered(builder, out var endpointRouteBuilder);
configure(endpointRouteBuilder);
// Yes, this mutates an IOptions. We're registering data sources in a global collection which
// can be used for discovery of endpoints or URL generation.
//
// Each middleware gets its own collection of data sources, and all of those data sources also
// get added to a global collection.
var routeOptions = builder.ApplicationServices.GetRequiredService<IOptions<RouteOptions>>();
foreach (var dataSource in endpointRouteBuilder.DataSources)
{
routeOptions.Value.EndpointDataSources.Add(dataSource);
}
return builder.UseMiddleware<EndpointMiddleware>();
}
ASP.NET Core 3 uses a refined endpoint routing which will generally give more control about routing within the application. Endpoint routing works in two separate steps:
In a first step, the requested route is matched agains the configured routes to figure out what route is being accessed.
In a final step, the determined route is being evaluated and the respective middleware, e.g. MVC, is called.
The two steps are set up by app.UseRouting() and app.UseEndpoints(). The former will register the middleware that runs the logic to determine the route. The latter will then execute that route.
Also, refer to:
https://asp.net-hacker.rocks/2019/08/12/aspnetcore30-look-into-startup.html https://aregcode.com/blog/2019/dotnetcore-understanding-aspnet-endpoint-routing/

How to configure emberjs routes in SpringMVC?

We have an Ember frontend and Spring Boot backend.
When Ember runs standalone on port 4200 and the Spring Boot backend on 8080, then everything works. But this scenario is somewhat unusual for production environments, not only because of CORS problem. The URL of the backend must be known already on build time (!) of the Ember application, because it's integrated within the compiled ember app. This is not possible for many projects. Therefore, we want to integrate the frontend Ember App in the Spring Boot backend, which is usual for e.g. SPA with AngularJS.
The Ember app (from /dist) is thus copied to src/main/resource/static. After adjusting the rootURL and API.host with the Ember app that works very well.
The problem arises now, when a manual reload for an URL is made in the browser. Such a URL is now an Ember route. The http-request arrives at the Spring Boot backend which don't knows the route and we got a 404 error.
How should SpringMVC (as part of the Spring Boot backend) answers the httpRequest for such a route, so that the Ember app continue their work and handle the request ?
HTML Page request (by browser)
http://host/springBootAppContext/index.html => src/main/resource/static/index.html (ember app)
REST API request (by Ember App)
http://host/springBootAppContext/users => RESTController mapped for /users
Ember Routing (by Ember App)
http://host/springBootAppContext/user-list => ???
You can't provide a normal Spring MVC #Controller class because the ModelView response is interpretet as user-list.html or similar which doesn't exist
after tests with different solutions I came up with a really simple one.
Provide a normal, non-REST controller with request mappings for every route defined by the ember app. Every such request have to be answered with the view name of the ember app start page (index.html in most cases). The browser loads that html page and starts the containing ember app. The ember app detects the route (because the route was part of the http request) and work according all specified route configurations (template, model, controller).
No 404 NotFound any more.
#Controller
public class EmberRouteController {
public static final String INDEX = "index.html";
#RequestMapping(value = "/ember-route-1", method = RequestMethod.GET)
public String emberRoute1() {
return INDEX;
}
#RequestMapping(value = "/ember-route-2", method = RequestMethod.GET)
public String emberRoute2() {
return INDEX;
}
}
The previous answer helped me a lot. But I was still thinking of better solution than creating backend APIs for each route. And I feel the better solution would be to put '#' in before ember route then ember routes serves the request rather than going to the backend server.
Router.reopen({
location: 'hash'
});
Ex: http://localhost:8008/#/first
Here first is my route. And I have put # in the URL, now reload of the page is working.
Hope this will help.

ASP.NET MVC Only use route to access controller action

I have a controller action that I only want users to be able to access by using a friendly route.
So instead of going to "/controller/action"
They should only be able to go to "/controller-action"
This is the route I have setup for this.
routes.MapRoute("ControllerAction",
"controller-action",
new { controller = "Controller", action = "Action" });
Is there any way to keep this route to this controller/action while redirecting requests from /controller/action to /controller-action ?
The reason this is being asked for is to keep our paths "less deep" for seo reasons.

ASP.NET Web API 2 re-routing

I am building a restful services for my data using ASP.NET web api 2.
In the data model, I have an entity called "ServiceProvider" which provide "Service"(s).
so, I am building restful for those two entities.
the requirements is to build two restful services, one as follow
api/serviceProvider/{id}/services
which gives list of services provided by that provider.
as well, the requirements is to give the same data (services by provider) through this rest service
api/services?serviceProviderId={providerId}
so, I created two controllers, for "serviceProvider", and for "Service"
I already implemented the second call, by creating an action method in the "Service" controller with this signature
public IEnumerable<Service> GetServiceByProvider(int providerId)
because both are going to run the same code, can I just re-route the first call to the second one?
At the same time, not effecting the other actions in both controllers??
I tried to do this is the webApiConfig with no success
config.Routes.MapHttpRoute(name: "serviceByProvider",
routeTemplate: "api/serviceProvider/{id}/services",
defaults: new { controller = "Service", action = "GetServicesByProvider" });
where the "GetServiceByProvider" is the method name in the "Service" controller that will serve the second call
but without success
As I said there are other actions in both controllers I don't want to affect them by this routing.
Like I have the following
api/serviceProvider
api/serviceProvider/{id}
api/services/
api/services/{id}
.....
I decided to try again and duplicate your environment and found a problem in your route template. The parameter your route is expecting is called id but your GetServicesByProvider method accepts a parameter called providerId. The framework is looking for parameters with the same name. Changing this should get your routing working the way you want it to AND maintain all of your previous routes.
config.Routes.MapHttpRoute(
name: "serviceByProvider",
routeTemplate: "api/serviceProvider/{providerId}/services",
defaults: new { controller = "Service", action = "GetServicesByProvider" }
);

404 after setting non-default ASP.net MVC routes

I'm using ASP.net MVC4 with VWD Express 2010. I've set up an extra route to remove the extraneous /Home/ from URLs, as suggested for example here and here. I made sure to put them in the right order:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Home",
url: "{action}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
This works as far as removing /Home/ is concerned, but now I get 404 when trying to access non-default controllers:
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: /LogItem/
I've tracked it down to the route, since if I remove the non-default one, it works fine again. I'm not sure what I'm doing wrong however, and by my understanding of other answers and the docs, this should work.
Edit: Since it's apparently not clear from my description, I added the "Home" route to be able to link to /About/ instead of /Home/About, etc. It was the suggested solution I found after googling. I basically want it to match actions implemented by HomeController with shorthand URLs (/{action}), as well as any other controller I also add in full (/{controller}/{action}/{optional id})
Routes are evaluated on a first-come, first-served basis. Your "Home" route basically says "If you see a URL with just one segment - grab it and handle it, then assume that segment is the action. When that happens, the second route you've registered doesn't get a chance to handle the request.
With the specific error as an example, you are requesting "/LogItem". The Home route kicks in, parses "LogItem" as the name of the action, and passes it to the default controller. Since that controller maybe doesn't have a LogIn action, a 404 is thrown.
One solution is to change the order of the routes. But even then, those two are overlapping, since the 2nd will also handle URLs with 1 segment, but interpret that segment as the controller. It will execute the default action (Index) rather than passing the handling to the next route.
Why do you need the first route? What are you trying to achieve? If you provide more context we can figure out a way to implement those routes.

Resources