No route matches the supplied values

No route matches the supplied values



This particular case should not be a duplicate of any other thread - I believe I've checked them all and I don't believe any refer to this case specifically.



I have this 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);





Here is the CreateMonitorRequest class code:


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;




Here is the MonitorDTO class code:


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;




I make the following call in 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"



Per the code, the expected return is a Guid which represents the newly-created MonitorId. Instead, I receive a 500 Internal Server Error with no details. However, the record is successfully created in the database. (SQL Server 2016).


500 Internal Server Error



The log shows this as the error:


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



I have another Controller in this project with very similar syntax and all is working well with it. I don't see any differences between the two that would indicate to me why this one doesn't work.



What could be causing this error, and how is the record still getting created in the database?



EDIT: added additional code for proper context to contribute to the answer provided by @anserk





I'm assuming you've examined the logs and nothing about the error is in there? What does your CreatedAtAction do? It could be returning 500 without throwing anything...
– Ron Beyer
Aug 27 at 17:41


CreatedAtAction





The above-posted error is all I'm told as far as logs go. I'm afraid I'm not well-equipped to answer your question about what CreatedAtAction does? I'm still very much a beginner at this. Any additional information you can provide so I can help you help would be greatly appreciated.
– Stpete111
Aug 27 at 18:13




1 Answer
1



The CreatedAtAction returns an URI to the entity you just created. In your controller you didn't define the action ("GET") for getting the resource. You should add a new action for it.


CreatedAtAction



DTO:


public class MonitorDto

public string QueryMonitorId get; set;,
pubcli string SubjectId get; set;



In your 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 );



More information about https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.createdataction?view=aspnetcore-2.1





it probably would have helped if I included ALL of the code for the Controller. Due to my newbie-ism, I didn't think I needed to include anything other than the piece that was related to the call I've made. There is a GET action in the Controller. I have edited my post to include the code for the entire controller (note the Get action before the Post action, as well as the GetClientId method at the end. I've also included the existing MonitorDTO class for reference. So then do you think the GET action needs to be updated along the lines of your suggestion? Thanks.
– Stpete111
Aug 28 at 1:45





You have to give your action the name Get, see [HttpGet("queryMonitorId/subjectId", Name = "Get")]. CreatedAtAction use that name to reference the action. Make sure that you are using the right key for the GET, in your CreatedAtAction method looks like it should have a composite key: queryMonitorId = response.MonitorId.Id, subjectId = request.SubjectId
– anserk
Aug 28 at 1:50


Get


[HttpGet("queryMonitorId/subjectId", Name = "Get")]


queryMonitorId = response.MonitorId.Id, subjectId = request.SubjectId





Yes, also check the route values you pass in the CreatedAtAction. You pass both queryMonitorId and subjectId while in your GET you only expect an Id.
– anserk
Aug 28 at 1:59


CreatedAtAction


queryMonitorId


subjectId


Id





To me it looks like queryMonitorId = response.MonitorId.Id should be tyour Monitor Id.
– anserk
Aug 28 at 12:19


queryMonitorId = response.MonitorId.Id





Let us continue this discussion in chat.
– anserk
Aug 28 at 14:47






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

How do I collapse sections of code in Visual Studio Code for Windows?

ャフサォクコ ケウ,コ,ワ メ,ロスョノ゙,クネ,フムカヤヲニ,エコ゚ツ ウイオン゙ケワサネォキモュキォウイノンコチ゚メヌナイゥフュ,カヒウネェ ネ,ホノケ,ムュキ ッボーミュハ,チ ツス ィ メウイマヤ,゙ウチ ヅ ロ,ォジヌェ ャヌット ェ,マャ,チナエヒネソキツテ トホヲヲミーァ