Context.Request.Query["id"] return null in View - asp.net-core-mvc

I want to get "id" parameter in View, but Context.Request.Query["id"] return null value.
Query like this:localhost:1000/MyController/Getuser/65190907-1145-7049-9baa-d68d44b1ad06
// Controller
public ActionResult Getuser(Guid id)
{
//HttpContext.Request.Query["id"] also return null
return View();
}
//in startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}

I think I can get it by ViewContext.ModelState["id"].AttemptedValue

Request.Query contains query string of the request, i.e. URL part that goes after question mark: ...?param1=value1&param2=value2. URL localhost:1000/MyController/Getuser/65190907-1145-7049-9baa-d68d44b1ad06 does not contain query string. GUID 65190907-1145-7049-9baa-d68d44b1ad06 is just a part of URL path.
If for some reason you want to access id parameter from raw request, not via Model Binding, you have two options:
Pass id in query string and access it via HttpContext.Request.Query["id"]:
In this case request URL will be http://localhost:1000/MyController/Getuser?id=65190907-1145-7049-9baa-d68d44b1ad06. No changes in routes are required.
The second option is to extract id from Request.Path:
public IActionResult Getuser(Guid id)
{
var path = HttpContext.Request.Path;
var id2 = Guid.Parse(path.Value.Split('/').Last());
return View();
}

Related

MVC Web API Routing to Wrong Action

I have a web API controller, when I call the default Get action this works, when I call another specific action (GetReservationsForCustomer) this also works, but one action gives an error (GetReservationsByDate), it seems to route to the default Get action. Here is the code:
// GET: api/Reservations
public IQueryable<Reservation> GetReservations()
{
return db.Reservations;
}
[ResponseType(typeof(ReservationDTO))]
public IHttpActionResult GetReservationsForCustomer(int CustomerId)
{
IEnumerable<Reservation> reservations = db.Reservations.Where(r => r.CustomerId == CustomerId).ToList();
List<ReservationDTO> reservationList = new List<ReservationDTO>();
foreach(Reservation reservation in reservations)
{
reservationList.Add(new ReservationDTO
{
id = reservation.id,
ReservationStart = reservation.ReservationStart,
Covers = reservation.Covers
});
}
return Ok(reservationList);
}
[ResponseType(typeof(ListReservationDTO))]
public IHttpActionResult GetReservationsByDate(DateTime StartDate, DateTime EndDate)
{
IEnumerable<Reservation> reservations = new List<Reservation>();
if (EndDate != null)
{
reservations = db.Reservations.Where(r => r.ReservationStart.Date >= StartDate.Date && r.ReservationStart.Date >= EndDate.Date).ToList();
}
else
{
reservations = db.Reservations.Where(r => r.ReservationStart.Date == StartDate.Date).ToList();
}
List<ReservationDTO> reservationList = new List<ReservationDTO>();
foreach (Reservation res in reservations)
{
reservationList.Add(new ReservationDTO
{
id = res.id,
ReservationStart = res.ReservationStart,
Covers = res.Covers,
CustomerEmail = res.Customer.EmailAddress,
CustomerName = res.Customer.Name,
CustomerPhone = res.Customer.PhoneNumber
});
}
return Ok(reservationList);
}
Here is my API call:
http://localhost:55601/api/Reservations/GetReservationsByDate/?StartDate=2018-03-04:T12:30:00
And here is the response:
{
"Message": "The request is invalid.",
"MessageDetail": "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Http.IHttpActionResult GetReservation(Int32)' in 'GreenLionBookings.API.ReservationsController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
}
Please note the specifics of the action are not relevant at this stage, I've butchered it a fair bit trying to get this to work! I've tried specifying a start date and end date and neither seems to work. It always seems to get routed to the default Get action.
Here is my RouteConfig:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
And here is my WebApiConfig:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
So both basically just default.
Why is this not routing to the correct action, just for this one and not the others? I have another controller (Customers) which seems to work correctly for all actions too. I've read this and this, and also this and this which I actually thought was pretty relevant and quite helpful, but didn't solve my problem.
What am I doing wrong here?
First of all, you have a typeo in the date.
This 2018-03-04:T12:30:00 should be 2018-03-04T12:30:00.
Then, to solve the routing problem, you could leave out the action name of the url and let the framework match the request against the parameters name.
Try it like this
api/Reservations?StartDate=2018-03-04T12:30:00&EndDate=2018-03-05T12:30:00
Then, if you want to be able to send nullable values to EndDate which is a value type of DateTime; make the DateTime nullable
[ResponseType(typeof(ListReservationDTO))]
public IHttpActionResult GetReservationsByDate(DateTime StartDate, DateTime? EndDate)
Notice the DateTime? which is a shorthand for Nullable<DateTime>

ASP.NET core HttpGet single Web API

Good Morning,
I’m having difficulty setting up my HTTPGETs and then testing the solution in Postman.
I’m trying to return a single result on both occasions however when I input the parameters nothing loads. So I'm clearly missing something which i need some help on please.
I have 1 parameter {id} in my CashMovementController and if I navigate to localhost/api/cashmovements/{id} it loads however if pass the {id} parameter in postman it fails.
Then in my BondCreditRatingsController I have 2 parameters {ISIN} & {Date} and again I'm not sure how to approach this.
Love to hear some advice/help on this please
Thanks GWS
Startup.cs
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
CashMovementsController.cs
[Route("api/[controller]")]
public class CashMovementsController : Controller
{
private ICashMovementRepository _cashmovementRepository;
[HttpGet("{id}", Name = "GetCashMovement")]
public IActionResult Get(int id)
{
CashMovement _cashmovement = _cashmovementRepository.GetSingle(u => u.CashMovementId == id);
if (_cashmovement != null)
{
CashMovementViewModel _cashmovementVM = Mapper.Map<CashMovement, CashMovementViewModel>(_cashmovement);
return new OkObjectResult(_cashmovementVM);
}
else
{
return NotFound();
}
}
}
BondCreditRatingsController.cs
[Route("api/[controller]")]
public class BondCreditRatingsController : Controller
{
private IBondCreditRatingRepository _bondcreditratingRepository;
public BondCreditRatingsController(IBondCreditRatingRepository bondcreditratingRepository)
{
_bondcreditratingRepository = bondcreditratingRepository;
}
[HttpGet("{id}", Name = "GetBondCreditRating")]
public IActionResult Get(string id, DateTime efffectivedate)
{
BondCreditRating _bondcreditrating = _bondcreditratingRepository.GetSingle(u => u.ISIN == id, u => u.EffectiveDate == efffectivedate);
if (_bondcreditrating != null)
{
BondCreditRatingViewModel _bondcreditratingVM = Mapper.Map<BondCreditRating, BondCreditRatingViewModel>(_bondcreditrating);
return new OkObjectResult(_bondcreditratingVM);
}
else
{
return NotFound();
}
}
If you want to map it to api/Controller/method/id you would need to use the code below because you want to map parameter order (no other identifier) to a specific parameter name in the action.
[HttpGet("GetCashMovement/{id}")]
Your current code should work with below since you are using named parameters and because the request can't be mapped to any other template.
/api/CashMovements/GetCashMovement?id=1
But that attribute syntax will also (possibly unintentionally) trigger:
/api/CashMovements/1
Since a sum of your defined template for that action is:
[Route("api/[controller]/{id}")]
Reason to why /api/ApiTest/GetCashMovement maps GetCashMovement.Get(int i) is because id is defined as optional in startup
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/**{id?}**");
A question mark (?) after the route parameter name defines an optional
parameter.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-3.0#create-routes

How to use ASP.Net 5 CreatedAtAction

I'm trying to do an HttpPost to create an entity and I want to return a 201 created with the location header set to https://mysite/api/entity/1. I can't figure out how to do this while returning an IActionResult.
Calling it like this
return CreatedAtAction("Get", new { id = entity.Id }, "/{id}");
I get https://mysite/api/entity?id=11
I can't figure out how to get what I want.
I assign a route name to the Get action and reference it by name to make this work. For example:
// GET api/values/5
[HttpGet("{id}", Name="GetAction")]
public string Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public IActionResult Post([FromBody]string value)
{
return this.CreatedAtRoute(
"GetAction", new { id = 5 }, new { id = 5 });
}

Url routing in mvc 3.0

I want to have below specific Url routing for my website
http://www.MyWebsite?Region=US&Area=South
based on passed Region and Area query string parameter, i want to redirect to a specific controller action.
Problems:
What should be the Url Routing ?
Whether creating a common controller action which redirects to specific action will work here?
Any help would be greatly appriciated !!
Thanks
If you want to do querystring right off the root, then you need to map routes in global this way. Inside your action you can access context and grab querystring from it. Below is my example to do twitter style usernames, but idea is the same.
routes.MapRoute("UserSettings",
"{username}/settings",
new { controller = "Home", action = "Settings", username = "" },
new { username = new NotNullOrEmptyConstraint() }
);
public class NotNullOrEmptyConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
try
{
return !String.IsNullOrEmpty(values["username"].ToString());
}
catch (Exception)
{
return false;
}
}
}
public ActionResult Settings(string username){
}

How do I validate for a empty query string parameter in asp.net mvc3

I want to validate for a empty Id value in the url.
../Task/EditEmployee/afccb22a-7cfd-4be5-8f82-9bd353c13b16
I want that if the Id is empty
../Task/EditEmployee/
Than redirect the user to a certain page.
public ActionResult EditEmployee(Guid Id)
{
//Some code in here
}
It may not be the best solution but you can take id parameter as string and try to parse it like this:
public ActionResult EditEmployee(string id)
{
if(string.IsNullOrWhiteSpace(id))
{
// handle empty querystring
}
else
{
Guid guid;
if (Guid.TryParse(id, out guid))
{
//Some code in here
}
}
}
Or
You can also create a regex constraint on the route but that may be too complicated and hard to understand. Map this route before the default one.
routes.MapRoute(
"TastEditEmployee",
"Task/EditEmployee/{id}",
new { controller = "Task", action = "EditEmployee" },
new { id = #"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$" }
);
Then you can use id parameter as Nullable Guid.
public ActionResult EditEmployee(Guid? id)
{
//do something
}
Since Guid is a struct, the value of Id will be Guid.Empty if it was omitted. You can check for that.
public ActionResult EditEmployee(Guid Id)
{
if (Id == Guid.Empty) throw new ArgumentException("Id not specified.");
}

Resources