c# - 没有路由与提供的值匹配

标签 c# asp.net-mvc asp.net-web-api

这个特殊案例不应该与任何其他线程重复 - 我相信我已经检查了所有这些并且我不相信任何人专门提到这个案例。

我有这个 Controller :

 namespace Cantrel.Application.CantrelSearchApi.Controllers
    {
        [Route("api/[controller]")]
        [Authorize]
        public class MonitorsController : Controller
        {
            private readonly IMonitoringApiService monitoringService;
            private readonly IClientsApiService clientsService;
            private readonly ILogger<MonitorsController> logger;

            public MonitorsController(IMonitoringApiService monitoringService,
                IClientsApiService clientsService,
                ILogger<MonitorsController> logger)
            {
                this.monitoringService = monitoringService;
                this.clientsService = clientsService;
                this.logger = logger;
            }


  [HttpGet("{id}")]
        public async Task<IActionResult> Get(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                return BadRequest("No id was provided. Please provide a valid monitor id or subject id.");
            }

            try
            {
                MonitorDto monitor;

                if (Guid.TryParse(id, out Guid monitorId))
                {
                    monitor = await GetByMonitorId(monitorId);
                }
                else
                {
                    monitor = await GetBySubjectId(id);
                }

                if (monitor == null)
                {
                    return NotFound();
                }

                return Json(monitor);
            }
            catch (Exception ex)
            {
                logger.LogError($"[{Request.Path.Value}]: {ex.ToString()}");
                return new StatusCodeResult(500);
            }
        }

     [HttpPost]
        public async Task<IActionResult> Post([FromBody] MonitorsPostRequest request)
        {
            //logger.LogError("We are here"); <--

            if (request == null)
            {
                return BadRequest("Request could not be parsed.");
            }

            if (string.IsNullOrEmpty(request.SubjectId))
            {
                return BadRequest("SubjectId is required for a monitor.");
            }

            if (string.IsNullOrEmpty(request.Subject))
            {
                return BadRequest("Subject is required for a monitor.");
            }

            if (request.BillingCodeId == Guid.Empty)
            {
                return BadRequest("A billing code is required for a monitor.");
            }

            try
            {
                var clientId = GetClientId();
                var billingCodeId = new BillingCodeId(request.BillingCodeId);

                //check permissions <--
                var permissions = await clientsService.AuthorizeSearchLicenseAsync(
                    new SearchAuthorizationRequest()
                    {
                        ClientId = clientId,
                        BillingCodeId = billingCodeId,
                        Categories = request.Categories?.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
                    });

                if (!permissions.Success)
                {
                    if (!permissions.BillingCodeValid)
                    {
                        return BadRequest($"The billing code provided is not active for the account.");
                    }

                    if (permissions.Licensing == null)
                    {
                        return BadRequest($"The User does not have access to requested functionality, please contact sales if you would like to include additional permission or if your permissions are incorrect.");
                    }
                    else
                    {
                        return BadRequest($"The User does not have access to {string.Join(", ", permissions.Licensing.Select(l => l.Categories))} Categories, please contact sales if you would like to include additional permission or if your permissions are incorrect.");
                    }
                }

                var createRequest = new CreateMonitorRequest()
                {
                    ClientId = clientId,
                    BillingCodeId = billingCodeId,
                    Subject = request.Subject,
                    SubjectId = request.SubjectId,
                    Categories = request.Categories?.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries),
                    NeedsTranslation = request.NeedsTranslation,
                    Parameters = request.Parameters
                };

                if (request.Schedule != null)
                {
                    createRequest.StartAt = request.Schedule.StartAt;
                    createRequest.EndAt = request.Schedule.EndAt;
                    if (Enum.TryParse<ScheduleTypeId>(request.Schedule.ScheduleType, out ScheduleTypeId scheduleType))
                    {
                        createRequest.ScheduleType = scheduleType;
                    }
                }

                var response = await monitoringService.CreateMonitorAsync(createRequest);
                if (response.Duplicate)
                {
                    return BadRequest($"Subject Id [{request.SubjectId}] is already being monitored with monitor {response.MonitorId.Id}.");
                }
                else
                {
                    return CreatedAtAction("Get",
                        new
                        {
                            queryMonitorId = response.MonitorId.Id,
                            subjectId = request.SubjectId
                        },
                        JsonConvert.SerializeObject(
                            new
                            {
                                queryMonitorId = response.MonitorId.Id,
                                subjectId = request.SubjectId
                            }));
                }
            }
            catch (RequiredFieldException rfe)
            {
                return BadRequest(rfe.Message);
            }
            catch (Exception ex)
            {
                logger.LogError($"[{Request.Path.Value}]: {ex.ToString()}");
                return new StatusCodeResult(500);
            }
        }

 private ClientId GetClientId()
        {
            var client_id = int.Parse(HttpContext.User.Claims.First(c => c.Type == TokenProviderOptions.ClientIdClaimName).Value);
            return new ClientId(client_id);
        }
        private async Task<MonitorDto> GetByMonitorId(Guid monitorId)
        {
            return await monitoringService.GetMonitorByIdAsync(new MonitorId(monitorId));
        }
        private async Task<MonitorDto> GetBySubjectId(string id)
        {
            return await monitoringService.GetMonitorBySubjectIdAsync(GetClientId(), id);
        }
    }
}

这是 CreateMonitorRequest 类代码:

namespace Cantrel.Application.Contracts.Monitoring.Requests
{
    [DataContract]
    public class CreateMonitorRequest
    {
        public CreateMonitorRequest();

        [DataMember]
        public ClientId ClientId { get; set; }
        [DataMember]
        public BillingCodeId BillingCodeId { get; set; }
        [DataMember]
        public string SubjectId { get; set; }
        [DataMember]
        public ScheduleTypeId? ScheduleType { get; set; }
        [DataMember]
        public DateTime? StartAt { get; set; }
        [DataMember]
        public DateTime? EndAt { get; set; }
        [DataMember]
        public string Subject { get; set; }
        [DataMember]
        public List<string> Aliases { get; set; }
        [DataMember]
        public string[] Categories { get; set; }
        [DataMember]
        public bool NeedsTranslation { get; set; }
        [DataMember]
        public Dictionary<string, string> Parameters { get; set; }
    }
}

这是 MonitorDTO 类代码:

namespace Cantrel.Application.Contracts.Monitoring.Dtos
{
    [DataContract]
    public class MonitorDto
    {
        [DataMember]
        public MonitorId Id { get; set; }
        [DataMember]
        public ClientId ClientId { get; set; }
        [DataMember]
        public BillingCodeId BillingCodeId { get; set; }
        [DataMember]
        public string SubjectId { get; set; }
        [DataMember]
        public DateTime CreatedAt { get; set; }
        [DataMember]
        public MonitorScheduleDto Schedule { get; set; }
        [DataMember]
        public MonitorSearchDto Search { get; set; }
        [DataMember]
        public MonitorStatus Status { get; set; }
        [DataMember]
        public string SubjectTranslated { get; set; }
        [DataMember]
        public string AliasTranslated { get; set; }
    }
}

我在 Postman 中进行以下调用:

POST: {{api}}/Monitors

Body:
{
  "clientid":"1",
  "billingcodeid":"ABCDEFGH-1234-4567-8901-ABCDEFGHIJKL",
  "subject": "John Doe",
  "subjectId":"Test1234",
  "ScheduleType" : "1",
  "Categories": "GENER",
  "parameters":
   {"dateofbirth":"8/07/2018"}
}

根据代码,预期返回是一个 Guid,表示新创建的 MonitorId。相反,我收到了一个没有详细信息的 500 Internal Server Error。但是,已在数据库中成功创建记录。(SQL Server 2016)。

日志将此显示为错误:

[ERR] Connection id ""0HLGC42CD408N"", Request id ""0HLGC42CD408N:00000004"": An unhandled exception was thrown by the application. (560e7d32)
System.InvalidOperationException: No route matches the supplied values.
   at Microsoft.AspNetCore.Mvc.CreatedAtActionResult.OnFormatting(ActionContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor.ExecuteAsync(ActionContext context, ObjectResult result)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeResultAsync>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---

我在这个项目中有另一个 Controller ,语法非常相似,并且一切正常。我看不出这两者之间有任何区别可以告诉我为什么这个不起作用。

可能导致此错误的原因是什么,以及如何在数据库中创建记录?

编辑:为适当的上下文添加了额外的代码,以有助于@anserk 提供的答案

最佳答案

CreatedAtAction 将 URI 返回到您刚刚创建的实体。在您的 Controller 中,您没有定义获取资源的操作(“GET”)。您应该为其添加一个新操作。

DTO:

public class MonitorDto 
{
    public string QueryMonitorId {get; set;},
    public string SubjectId {get; set;}
}

在你的 Controller 中:

...
[HttpGet("{queryMonitorId}/{subjectId}", Name = "Get")]
public async Task<IActionResult> GetMonitor(string queryMonitorId, string subjectId)
{
    ...
    // Your get implementation here.
    Ok(new MonitorDto { QueryMonitorId = queryMonitorId, SubjectId = subjectId });
}

关于 https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.createdataction?view=aspnetcore-2.1 的更多信息

关于c# - 没有路由与提供的值匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52044381/

相关文章:

c# - 以编程方式确定 SQL Server Compact sdf 文件的大小

asp.net - HTTP 403 禁止 : Access is denied ASP. NET Web API

c# - Expression Blend 示例数据和数据模板

c# - 在整个程序 c# 中调用变量时出现问题

c# - 如何检查 System.IO.File.Delete 是否成功删除文件

asp.net-mvc - ASP.NET MVC2 和日期时间格式

c# - HttpRequestMessage.Content 在 ASP.Net Web API 中的日志记录 DelegatingHandler 中读取时丢失

asp.net-web-api - ASP.NET Web API - 删除时出现 404

c# - 有条件地在 html.RadioButtonFor (MVC4/Razor) 中包含 checked 属性

c# - NDepend 中解决方案范围的命名空间依赖关系图