没有路线与提供的值匹配

时间:2018-08-27 17:36:15

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

这种特殊情况不应与其他任何线程重复-我相信我已经检查了所有这些线程,并且我不认为有任何专门提及此情况的

我有这个控制器:

 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; }
    }
}

我用邮递员打了以下电话:

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 ---

我在这个项目中有另一个控制器,其语法非常相似,并且都很好用。我看不到两者之间的任何差异,这可以向我说明为什么这个无效。

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

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

1 个答案:

答案 0 :(得分:2)

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

DTO:

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

在您的控制器中:

...
[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://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.createdataction?view=aspnetcore-2.1

的更多信息