I'm having trouble getting routing in Angular2/.Net Core to work properly.
I've started a default .Net Core web project with Angular, and have successfully created a new controller with the applicable view components. The page's purpose is to display a list of documents and give you the option to click the title to see each document in a separate view.
So long everything works, it displays the contents of the page and I can also display a list of documents retrieved from the database. The routing looks like this:
@NgModule({
declarations: [
AppComponent,
NavMenuComponent,
DocumentsComponent,
HomeComponent
],
imports: [
CommonModule,
HttpModule,
FormsModule,
RouterModule.forRoot([
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'documents', component: DocumentsComponent },
{ path: '**', redirectTo: 'home' }
])
]
})
export class AppModuleShared {
}
I have a link on each document so that when you click it you are transferred from the list /documents
to eg. /documents/1
When I click on a link it only stays there long enough so I can see the URL change and then it goes to the default fallback /home
.
In Startup.cs I have the default route handling set:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
From what I can tell the "default" map route should pick up /documents/1
but it doesn't. I never even gets to the backend method for the route.
[Produces("application/json")]
[Route("api/[controller]")]
public class DocumentsController : Controller
{
private readonly DatabaseContext _context;
public DocumentsController(DatabaseContext context)
{
_context = context;
}
// GET: api/Documents
[HttpGet]
public IActionResult GetDocuments()
{
// returns a JSON list of documents, works fine
}
// GET: api/Documents/5
[HttpGet("{id}")]
public async Task<IActionResult> GetDocument([FromRoute] int id)
{
//returns the specified document, is never even called
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var document = await _context.Documents.SingleOrDefaultAsync(m => m.Id == id);
if (document == null)
{
return NotFound();
}
return Ok(document);
}
What do I need to do to get the specific routes to work?
From what I can tell the "default" map route should pick up
/documents/1
but it doesn't.
Nope. The default route isn't configured that way. You must supply the action method name as the second parameter to match the default route.
/documents/getdocument/1
That said, it won't work. When you add an attribute route it automatically blocks the above route.
Therefore, the only URL that will work to get to DocumentsController.GetDocument(int)
is:
/api/documents/1
This is because you are defining [Route("api/[controller]")]
on your controller which makes every action in the controller prefixed this way.
If you want /documents/1
to be the URL and use attribute routing, you can use:
[Produces("application/json")]
[Route("documents")]
public class DocumentsController : Controller
{
private readonly DatabaseContext _context;
public DocumentsController(DatabaseContext context)
{
_context = context;
}
// GET: api/Documents
[HttpGet(Order = 2)]
public IActionResult GetDocuments()
{
// returns a JSON list of documents, works fine
}
// GET: api/Documents/5
[HttpGet("{id}", Order = 1)]
public async Task<IActionResult> GetDocument([FromRoute] int id)
{
//returns the specified document, is never even called
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var document = await _context.Documents.SingleOrDefaultAsync(m => m.Id == id);
if (document == null)
{
return NotFound();
}
return Ok(document);
}
}
Or if you want to use convention based routing, remove the [Route]
attribute from the controller, URL templates and Order
from HttpGet
above each action method and use:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "documents",
template: "documents/{id?}",
defaults: new { controller = "Documents", action = "GetDocuments" });
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
You need to tell the angular router that there is more after the documents
part of the path. It's looking for a component matched to the route /documents/1
and not finding it. If you add /:id
to your path it should allow it to map the second part of your url to a route instead of redirecting to home
{ path: 'documents/:id', component: DocumentsComponent },
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.