Centralize routing and dispatching functional test logic (#7938)

This commit is contained in:
James Newton-King 2018-06-19 23:24:15 +12:00 committed by GitHub
parent a0a9c2c585
commit 58aa16ee69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 1368 additions and 3149 deletions

15
Mvc.sln
View File

@ -170,8 +170,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPagesClassLibrary", "t
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Views.TestCommon", "test\Microsoft.AspNetCore.Mvc.Views.TestCommon\Microsoft.AspNetCore.Mvc.Views.TestCommon.csproj", "{51E3E785-A9D1-4196-BAFE-A17FF4304B89}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DispatchingWebSite", "test\WebSites\DispatchingWebSite\DispatchingWebSite.csproj", "{ABB3737F-E518-4E40-8A9C-F3281D610E8F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -896,18 +894,6 @@ Global
{51E3E785-A9D1-4196-BAFE-A17FF4304B89}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{51E3E785-A9D1-4196-BAFE-A17FF4304B89}.Release|x86.ActiveCfg = Release|Any CPU
{51E3E785-A9D1-4196-BAFE-A17FF4304B89}.Release|x86.Build.0 = Release|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Debug|x86.ActiveCfg = Debug|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Debug|x86.Build.0 = Debug|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Release|Any CPU.Build.0 = Release|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Release|x86.ActiveCfg = Release|Any CPU
{ABB3737F-E518-4E40-8A9C-F3281D610E8F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -977,7 +963,6 @@ Global
{E83D3745-9BCF-40E8-8D34-AFBA604C2439} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{17122147-ADFD-41C8-87D9-CCC582CCA8F9} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{51E3E785-A9D1-4196-BAFE-A17FF4304B89} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{ABB3737F-E518-4E40-8A9C-F3281D610E8F} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {63D344F6-F86D-40E6-85B9-0AABBE338C4A}

View File

@ -31,7 +31,6 @@
<ProjectReference Include="..\WebSites\BasicWebSite\BasicWebSite.csproj" />
<ProjectReference Include="..\WebSites\ControllersFromServicesWebSite\ControllersFromServicesWebSite.csproj" />
<ProjectReference Include="..\WebSites\CorsWebSite\CorsWebSite.csproj" />
<ProjectReference Include="..\WebSites\DispatchingWebSite\DispatchingWebSite.csproj" />
<ProjectReference Include="..\WebSites\ErrorPageMiddlewareWebSite\ErrorPageMiddlewareWebSite.csproj" />
<ProjectReference Include="..\WebSites\FilesWebSite\FilesWebSite.csproj" />
<ProjectReference Include="..\WebSites\FormatterWebSite\FormatterWebSite.csproj" />

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Admin
{
[Area("Admin")]
[Route("[area]/Users")]
public class UserManagementController : Controller
{
private readonly TestResponseGenerator _generator;
public UserManagementController(TestResponseGenerator generator)
{
_generator = generator;
}
[HttpGet("All")]
public IActionResult ListUsers()
{
return _generator.Generate("Admin/Users/All");
}
}
}

View File

@ -1,25 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Areas.Order
{
[Area("Order")]
[Route("Order/[action]", Name = "[area]_[action]")]
public class OrderController : Controller
{
private readonly TestResponseGenerator _generator;
public OrderController(TestResponseGenerator generator)
{
_generator = generator;
}
[HttpGet]
public IActionResult GetOrder()
{
return _generator.Generate("/Order/GetOrder");
}
}
}

View File

@ -1,30 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite
{
// This controller is reachable via traditional routing.
[Area("Travel")]
public class FlightController
{
private readonly TestResponseGenerator _generator;
public FlightController(TestResponseGenerator generator)
{
_generator = generator;
}
public IActionResult Index()
{
return _generator.Generate("/Travel/Flight", "/Travel/Flight/Index");
}
[HttpPost]
public IActionResult BuyTickets()
{
return _generator.Generate("/Travel/Flight/BuyTickets");
}
}
}

View File

@ -1,29 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Travel
{
[Area("Travel")]
public class HomeController : Controller
{
private readonly TestResponseGenerator _generator;
public HomeController(TestResponseGenerator generator)
{
_generator = generator;
}
public IActionResult Index()
{
return _generator.Generate("/Travel", "/Travel/Home", "/Travel/Home/Index");
}
[HttpGet("ContosoCorp/AboutTravel")]
public IActionResult About()
{
return _generator.Generate();
}
}
}

View File

@ -1,30 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite
{
[Area("Travel")]
[Route("ContosoCorp/Trains")]
public class RailController
{
private readonly TestResponseGenerator _generator;
public RailController(TestResponseGenerator generator)
{
_generator = generator;
}
public IActionResult Index()
{
return _generator.Generate("/ContosoCorp/Trains");
}
[HttpGet("CheckSchedule")]
public IActionResult Schedule()
{
return _generator.Generate("/ContosoCorp/Trains/Schedule");
}
}
}

View File

@ -1,52 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Controllers
{
public class BanksController : Controller
{
private readonly TestResponseGenerator _generator;
public BanksController(TestResponseGenerator generator)
{
_generator = generator;
}
[HttpGet("Banks/[action]/{id}")]
[HttpGet("Bank/[action]/{id}")]
public ActionResult Get(int id)
{
return _generator.Generate(
Url.Action(),
Url.RouteUrl(new { }));
}
[AcceptVerbs("PUT", Route = "Bank")]
[HttpPatch("Bank")]
[AcceptVerbs("PUT", Route = "Bank/Update")]
[HttpPatch("Bank/Update")]
public ActionResult UpdateBank()
{
return _generator.Generate(
Url.Action(),
Url.RouteUrl(new { }));
}
[AcceptVerbs("PUT", "POST")]
[Route("Bank/Deposit")]
[Route("Bank/Deposit/{amount}")]
public ActionResult Deposit()
{
return _generator.Generate("/Bank/Deposit", "/Bank/Deposit/5");
}
[HttpPost]
[Route("Bank/Withdraw/{id}")]
public ActionResult Withdraw(int id)
{
return _generator.Generate("/Bank/Withdraw/5");
}
}
}

View File

@ -1,29 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Controllers
{
// This controller contains actions mapped with a single controller-level route.
[Route("Blog/[action]/{postId?}")]
public class BlogController
{
private readonly TestResponseGenerator _generator;
public BlogController(TestResponseGenerator generator)
{
_generator = generator;
}
public IActionResult ShowPosts()
{
return _generator.Generate("/Blog/ShowPosts");
}
public IActionResult Edit(int postId)
{
return _generator.Generate("/Blog/Edit/" + postId);
}
}
}

View File

@ -1,63 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Controllers
{
// A controller can define a route for all of the actions
// in it and give it a name for link generation purposes.
[Route("api/Company/{id}", Name = "Company")]
public class CompanyController : Controller
{
private readonly TestResponseGenerator _generator;
public CompanyController(TestResponseGenerator generator)
{
_generator = generator;
}
// An action with the same template will inherit the name
// from the controller.
[HttpGet]
public ActionResult Get(int id)
{
return _generator.Generate(Url.RouteUrl("Company", new { id = id }));
}
// Multiple actions can have the same named route as long
// as for a given Name, all the actions have the same template.
// That is, there can't be two link generation entries with same
// name and different templates.
[HttpPut]
public ActionResult Put(int id)
{
return _generator.Generate(Url.RouteUrl("Company", new { id = id }));
}
// Two actions can have the same template and each of them can have
// a different route name. That is, a given template can have multiple
// names associated with it.
[HttpDelete(Name = "RemoveCompany")]
public ActionResult Delete(int id)
{
return _generator.Generate(Url.RouteUrl("RemoveCompany", new { id = id }));
}
// An action that defines a non empty template doesn't inherit the name
// from the route on the controller .
[HttpGet("Employees")]
public ActionResult GetEmployees(int id)
{
return _generator.Generate(Url.RouteUrl(new { id = id }));
}
// An action that defines a non empty template doesn't inherit the name
// from the controller but can perfectly define its own name.
[HttpGet("Departments", Name = "Departments")]
public ActionResult GetDepartments(int id)
{
return _generator.Generate(Url.RouteUrl("Departments", new { id = id }));
}
}
}

View File

@ -1,73 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Controllers
{
// This controller combines routes on the controller with routes on actions in a REST + navigation property
// style.
[Route("api/Employee")]
public class EmployeeController : Controller
{
private readonly TestResponseGenerator _generator;
public EmployeeController(TestResponseGenerator generator)
{
_generator = generator;
}
public IActionResult List()
{
return _generator.Generate("/api/Employee");
}
[AcceptVerbs("PUT", "PATCH")]
public IActionResult UpdateEmployee()
{
return _generator.Generate("/api/Employee");
}
[AcceptVerbs("PUT", "PATCH", Route = "Manager")]
public IActionResult UpdateManager()
{
return _generator.Generate("/api/Employee/Manager");
}
[HttpMerge("{id}")]
public IActionResult MergeEmployee(int id)
{
return _generator.Generate("/api/Employee/" + id);
}
[HttpGet("{id}")]
public IActionResult Get(int id)
{
return _generator.Generate("/api/Employee/" + id);
}
[HttpGet("{id}/Administrator")]
public IActionResult GetAdministrator(int id)
{
return _generator.Generate("/api/Employee/" + id + "/Administrator");
}
[HttpGet("~/Manager/{id}")]
public IActionResult GetManager(int id)
{
return _generator.Generate("/Manager/" + id);
}
[HttpDelete("{id}/Administrator")]
public IActionResult DeleteAdministrator(int id)
{
return _generator.Generate("/api/Employee/" + id + "/Administrator");
}
[Route("{id}/Salary")]
public IActionResult Salary(int id)
{
return _generator.Generate("/api/Employee/" + id + "/Salary");
}
}
}

View File

@ -1,31 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Controllers
{
[Route("Friends")]
public class FriendsController : Controller
{
private readonly TestResponseGenerator _generator;
public FriendsController(TestResponseGenerator generator)
{
_generator = generator;
}
[HttpGet]
[HttpGet("{id}")]
public IActionResult Get([FromRoute]string id)
{
return _generator.Generate(id == null ? "/Friends" : $"/Friends/{id}");
}
[HttpDelete]
public IActionResult Delete()
{
return _generator.Generate("/Friends");
}
}
}

View File

@ -1,39 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Controllers
{
// This controller is reachable via traditional routing.
public class HomeController : Controller
{
private readonly TestResponseGenerator _generator;
public HomeController(TestResponseGenerator generator)
{
_generator = generator;
}
public IActionResult Index()
{
return _generator.Generate("/", "/Home", "/Home/Index");
}
public IActionResult About()
{
// There are no urls that reach this action - it's hidden by an attribute route.
return _generator.Generate();
}
public IActionResult Contact()
{
return _generator.Generate("/Home/Contact");
}
public IActionResult OptionalPath(string path = "default")
{
return _generator.Generate("/Home/OptionalPath/" + path);
}
}
}

View File

@ -1,53 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Controllers
{
[Route("api/v1/Maps", Name = "v1", Order = 1)]
[Route("api/v2/Maps")]
public class MapsController : Controller
{
private readonly TestResponseGenerator _generator;
public MapsController(TestResponseGenerator generator)
{
_generator = generator;
}
[HttpGet]
public ActionResult Get()
{
// Multiple attribute routes with name and order.
// We will always generate v2 routes except when
// we explicitly use "v1" to generate a v1 route.
return _generator.Generate(
Url.Action(),
Url.RouteUrl("v1"),
Url.RouteUrl(new { }));
}
[HttpPost("/api/v2/Maps")]
public ActionResult Post()
{
return _generator.Generate(
Url.Action(),
Url.RouteUrl(new { }));
}
[HttpPut("{id}")]
[HttpPatch("PartialUpdate/{id}")]
public ActionResult Update(int id)
{
// We will generate "/api/v2/Maps/PartialUpdate/{id}"
// in both cases, v1 routes will be discarded due to their
// Order and for v2 routes PartialUpdate has higher precedence.
// api/v1/Maps/{id} and api/v2/Maps/{id} will only match on PUT.
// api/v1/Maps/PartialUpdate/{id} and api/v2/Maps/PartialUpdate/{id} will only match on PATCH.
return _generator.Generate(
Url.Action(),
Url.RouteUrl(new { }));
}
}
}

View File

@ -1,36 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Controllers
{
[Route("Order/[action]/{orderId?}", Name = "Order_[action]")]
public class OrderController : Controller
{
private readonly TestResponseGenerator _generator;
public OrderController(TestResponseGenerator generator)
{
_generator = generator;
}
[HttpGet]
public IActionResult Add(int orderId)
{
return _generator.Generate("/Order/Add/1");
}
[HttpPost]
public IActionResult Add()
{
return _generator.Generate("/Order/Add");
}
[HttpPut]
public IActionResult Edit(int orderId)
{
return _generator.Generate("/Order/Edit/1");
}
}
}

View File

@ -1,43 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Controllers
{
// This controller contains only actions with individual attribute routes.
public class StoreController : Controller
{
private readonly TestResponseGenerator _generator;
public StoreController(TestResponseGenerator generator)
{
_generator = generator;
}
[HttpGet("Store/Shop/Products")]
public IActionResult ListProducts()
{
return _generator.Generate("/Store/Shop/Products");
}
// Intentionally designed to conflict with HomeController#About.
[HttpGet("Home/About")]
public IActionResult About()
{
return _generator.Generate("/Home/About");
}
[Route("Store/Shop/Orders")]
public IActionResult Orders()
{
return _generator.Generate("/Store/Shop/Orders");
}
[HttpGet("Store/Shop/Orders")]
public IActionResult GetOrders()
{
return _generator.Generate("/Store/Shop/Orders");
}
}
}

View File

@ -1,72 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace DispatchingWebSite.Controllers
{
[Route("/Teams", Order = 1)]
public class TeamController : Controller
{
private readonly TestResponseGenerator _generator;
public TeamController(TestResponseGenerator generator)
{
_generator = generator;
}
[HttpGet("/Team/{teamId}", Order = 2)]
public ActionResult GetTeam(int teamId)
{
return _generator.Generate("/Team/" + teamId);
}
[HttpGet("/Team/{teamId}")]
public ActionResult GetOrganization(int teamId)
{
return _generator.Generate("/Team/" + teamId);
}
[HttpGet("")]
public ActionResult GetTeams()
{
return _generator.Generate("/Teams");
}
[HttpGet("", Order = 0)]
public ActionResult GetOrganizations()
{
return _generator.Generate("/Teams");
}
[HttpGet("/Club/{clubId?}")]
public ActionResult GetClub()
{
return Content(Url.Action(), "text/plain");
}
[HttpGet("/Organization/{clubId?}", Order = 1)]
public ActionResult GetClub(int clubId)
{
return Content(Url.Action(), "text/plain");
}
[HttpGet("AllTeams")]
public ActionResult GetAllTeams()
{
return Content(Url.Action(), "text/plain");
}
[HttpGet("AllOrganizations", Order = 0)]
public ActionResult GetAllTeams(int notRelevant)
{
return Content(Url.Action(), "text/plain");
}
[HttpGet("/TeamName/{*Name=DefaultName}/")]
public ActionResult GetTeam(string name)
{
return _generator.Generate("/TeamName/" + name);
}
}
}

View File

@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>$(StandardTestWebsiteTfms)</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Mvc\Microsoft.AspNetCore.Mvc.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,34 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Routing;
namespace DispatchingWebSite
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class HttpMergeAttribute : Attribute, IActionHttpMethodProvider, IRouteTemplateProvider
{
private static readonly IEnumerable<string> _supportedMethods = new[] { "MERGE" };
public HttpMergeAttribute(string template)
{
Template = template;
}
public IEnumerable<string> HttpMethods
{
get { return _supportedMethods; }
}
/// <inheritdoc />
public string Template { get; private set; }
/// <inheritdoc />
public int? Order { get; set; }
/// <inheritdoc />
public string Name { get; set; }
}
}

View File

@ -1,61 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
namespace DispatchingWebSite
{
// Generates a response based on the expected URL and action context
public class TestResponseGenerator
{
private readonly ActionContext _actionContext;
private readonly IUrlHelperFactory _urlHelperFactory;
public TestResponseGenerator(IActionContextAccessor contextAccessor, IUrlHelperFactory urlHelperFactory)
{
_urlHelperFactory = urlHelperFactory;
_actionContext = contextAccessor.ActionContext;
if (_actionContext == null)
{
throw new InvalidOperationException("ActionContext should not be null here.");
}
}
public JsonResult Generate(params string[] expectedUrls)
{
var link = (string)null;
var query = _actionContext.HttpContext.Request.Query;
if (query.ContainsKey("link"))
{
var values = query
.Where(kvp => kvp.Key != "link" && kvp.Key != "link_action" && kvp.Key != "link_controller")
.ToDictionary(kvp => kvp.Key.Substring("link_".Length), kvp => (object)kvp.Value[0]);
var urlHelper = _urlHelperFactory.GetUrlHelper(_actionContext);
link = urlHelper.Action(query["link_action"], query["link_controller"], values);
}
var attributeRoutingInfo = _actionContext.ActionDescriptor.AttributeRouteInfo;
return new JsonResult(new
{
expectedUrls = expectedUrls,
actualUrl = _actionContext.HttpContext.Request.Path.Value,
routeName = attributeRoutingInfo == null ? null : attributeRoutingInfo.Name,
routeValues = new Dictionary<string, object>(_actionContext.RouteData.Values),
action = ((ControllerActionDescriptor) _actionContext.ActionDescriptor).ActionName,
controller = ((ControllerActionDescriptor)_actionContext.ActionDescriptor).ControllerName,
link,
});
}
}
}

View File

@ -1,4 +0,0 @@
DispatchingWebSite
===
This web site illustrates how to use conventional and attribute dispatching.

View File

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using Microsoft.AspNetCore.Hosting;
namespace RoutingWebSite
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args)
.Build();
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseKestrel()
.UseIISIntegration();
}
}

View File

@ -42,21 +42,6 @@ namespace RoutingWebSite
"{controller}/{action}/{path?}");
});
}
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args)
.Build();
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseKestrel()
.UseIISIntegration();
}
}

View File

@ -14,9 +14,9 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
namespace DispatchingWebSite
namespace RoutingWebSite
{
public class Startup
public class StartupWithDispatching
{
// Set up application services
public void ConfigureServices(IServiceCollection services)
@ -33,46 +33,26 @@ namespace DispatchingWebSite
{
app.UseDispatcher();
//app.UseMvc(routes =>
app.UseEndpoint();
//app.UseMvcWithEndpoint(routes =>
//{
// routes.MapAreaRoute(
// routes.MapAreaEndpoint(
// "flightRoute",
// "adminRoute",
// "{area:exists}/{controller}/{action}",
// new { controller = "Home", action = "Index" },
// new { area = "Travel" });
// routes.MapRoute(
// routes.MapEndpoint(
// "ActionAsMethod",
// "{controller}/{action}",
// defaults: new { controller = "Home", action = "Index" });
// routes.MapRoute(
// routes.MapEndpoint(
// "RouteWithOptionalSegment",
// "{controller}/{action}/{path?}");
//});
app.UseEndpoint();
}
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConsole();
})
.Build();
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseKestrel()
.UseIISIntegration();
}
}
}