ASP.NET Core Model Binding from Route and Query String - asp.net

I would like to perform a GET request such as https://localhost:12345/api/employees/1/calendar/2018/2019?checkHistoricalFlag=true
I have created this method in my controller which works as expected:
[AllowAnonymous]
[HttpGet("/api/employees/{clockNumber:int}/calendar/{yearFrom:int}/{yearTo:int}")]
public IActionResult Get(int clockNumber, int yearFrom, int yearTo, bool checkHistoricalFlag = false)
{
return Ok();
}
However I would prefer to use the following view model:
public class DetailsQuery
{
[Required]
public int? ClockNumber { get; set; }
[Required]
public int? YearFrom { get; set; }
[Required]
public int? YearTo { get; set; }
public bool CheckHistoricalFlag { get; set; } = false;
}
This binds the route parameters but ignores "checkHistoricalFlag" from the query string:
[AllowAnonymous]
[HttpGet("/api/employees/{clockNumber:int}/calendar/{yearFrom:int}/{yearTo:int}")]
public IActionResult Get([FromRoute]DetailsQuery query)
{
return Ok();
}
Removing [FromRoute] results in a 415 "Unsupported Media Type" error.
Is it possible to bind both the route parameters and query string values to a single view model or do I need to specify the query string values separately?
[AllowAnonymous]
[HttpGet("/api/employees/{clockNumber:int}/calendar/{yearFrom:int}/{yearTo:int}")]
public IActionResult Get([FromRoute]DetailsQuery query, bool checkHistoricalFlag = false)
{
return Ok();
}

The comment from Imantas pointed me to using [FromQuery] on the view model which now looks like:
public class DetailsQuery
{
[Required]
public int? ClockNumber { get; set; }
[Required]
public int? YearFrom { get; set; }
[Required]
public int? YearTo { get; set; }
[FromQuery]
public bool CheckHistoricalFlag { get; set; } = false;
}
The controller method is now:
[AllowAnonymous]
[HttpGet("/api/employees/{clockNumber:int}/calendar/{yearFrom:int}/{yearTo:int}")]
public ActionResult Get([FromRoute]DetailsQuery query)
{
return Ok();
}
Which works as expected.
Thanks for the pointer Imantas.

Related

ASP.NET Core 3.1 ModelState validation fail for nullable

The issue I am having, is that if you provide a null value for an item, that is nullable, the ModelState.IsValid flags a validation error saying "The value ParentID is not valid for ParentID."
I want [int?] to allow null.
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
[Route("common/menu-setting/add")]
public IActionResult AddMenuSetting(Menu model)
{
if (!ModelState.IsValid)
{
ViewData["ParentMenus"] = _commonRepository.GetParentMenus();
return View(model);
}
var returnValue = _commonRepository.AddMenu(model);
if (!returnValue)
{
return RedirectToAction("AddMenuSetting");
}
return RedirectToAction("MenuSetting");
}
Model:
public class Menu
{
public int MenuID { get; set; }
public string MenuName { get; set; }
public int? ParentID { get; set; }
public string ParentMenuName { get; set; }
public int SortGroup { get; set; }
public int Sort { get; set; }
}

Get Id of inserted data (ASP.NET)

I have code in controller that write data from View to table
Here is code
[HttpGet]
public ActionResult WelcomeScreen()
{
// Формируем список команд для передачи в представление
SelectList teams = new SelectList(db.Vacancy, "VacancyId", "VacancyName");
ViewBag.Teams = teams;
SelectList teams2 = new SelectList(db.Companies, "CompanyID", "CompanyName");
ViewBag.Teams2 = teams2;
return View();
}
[HttpPost]
public ActionResult WelcomeScreen(Interview interview)
{
db.Interview.Add(interview);
db.SaveChanges();
int id = interview.Interview_Id;
return RedirectToAction("Index", "Questions");
}
Here is model
[Key]
public int Interview_Id { get; set; }
public string Greeting { get; set; }
public string Detail { get; set; }
public Nullable<int> VacancyId { get; set; }
public virtual Vacancy Vacancy { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Interwier> Interwiers { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<InvitationMail> InvitationMails { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<MassLink> MassLinks { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<QuestionBlock> QuestionBlocks { get; set; }
}
I need to have Interview_Id
I try to make it like this, but it not works int id = interview.Interview_Id;
How I can write id to variable?
If I understood your question right. You might have something like this.
public DbSet<Interview> Interviews {get; set;}
Rename Interview_Id to simply Id or InterviewId (no underscore).
public class Interview
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int InterviewId { get; set;}
// other properties
}
DAL Method.
public int Add(Interview inteview)
{
using(DbContext entities = new DbContext()
{
entities.Interviews.Add(interview);
entities.SaveChanges();
var id = interview.InterviewId;
return id;
}
}
From your Controller.
[HttpPost]
public ActionResult WelcomeScreen(Interview interview)
{
Dal dalObj = new Dal();
var inteviewId = dal.Add(interview);
//use this id
}
Hope this helps.
You can try this.
[HttpPost]
public ActionResult WelcomeScreen(Interview interview)
{
db.Interview.Add(interview);
db.SaveChanges();
int id = db.Interview.Max(x=>x.Interview_Id);
return RedirectToAction("Index", "Questions");
}
check you dbml
make sure you have this attribute set correctly
AutoSync=AutoSync.OnInsert
the full attribute usually like this
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true, UpdateCheck=UpdateCheck.Never)]

Cannot await 'long' when calling an async method inside asp.net mvc5

I have the following async method inside my asp.net mvc 5 web application with EF6:-
public async Task<Resource> GetResourceByName(string resourcename)
{
return await entities.Resources.SingleOrDefaultAsync(a => a.RESOURCENAME.ToLower() == resourcename.ToLower());
}
now i am trying to get the ID for the returned object from the above method as follow:-
var temp = await GetResourceByName(FQDN).Result.RESOURCEID;
but this will raise the following error:-
Error 1 Cannot await 'long'
now to fix this i did the following :-
var temp = await GetResourceByName(FQDN);
id = temp.RESOURCEID;
so not sure why my first apporach did not work. now i await the Task, and when it finises i will retrieve the .Result and get the ResourceID ... so why this will not work ?
here is the model for the Resource:-
public partial class Resource
{
public long RESOURCEID { get; set; }
public string RESOURCENAME { get; set; }
public Nullable<long> ACQUISITIONDATE { get; set; }
public Nullable<long> WARRANTYEXPIRY { get; set; }
public Nullable<long> EXPIRYDATE { get; set; }
public long COMPONENTID { get; set; }
public string ASSETTAG { get; set; }
public string SERIALNO { get; set; }
public string BARCODE { get; set; }
public Nullable<long> PURCHASELOTID { get; set; }
public Nullable<long> VENDORID { get; set; }
public long RESOURCESTATEID { get; set; }
public Nullable<long> SITEID { get; set; }
public Nullable<long> CIID { get; set; }
public bool ISDEPRECIATIONCONFIGURED { get; set; }
public bool ISDEPRECIATIONCALCULATED { get; set; }
public bool ISPERSONAL { get; set; }
public virtual ComponentDefinition ComponentDefinition { get; set; }
public virtual ResourceLocation ResourceLocation { get; set; }
public virtual ResourceState ResourceState { get; set; }
public virtual SiteDefinition SiteDefinition { get; set; }
}
Awaiting the task will give you the result. If you then want to descend into a property of the result, you'll need to use parenthesis if you want it all in one expression:
var temp = (await GetResourceByName(FQDN)).RESOURCEID;
Calling .Result on a task blocks the thread until the operation completes. The result object is of the type specified in TResult for the Task.
Your call did not work, because you can't await the Result of the task, only the task itself. Once you call .Result there is nothing to await.

How to use mutiple models for one dbset

NET MVC expetrts!
I'm new in asp.NET MVC 4, so I got a simple problem not to know how to solve!
so this is my NotActivatedUsers model :
public class NotActivatedUser
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
[Required]
[DefaultValue(false)]
public bool isActive { get; set; }
[Required, DataType(DataType.EmailAddress)]
public string email { get; set; }
[Required]
public string activeCode { get; set; }
public DateTime createDate { get; set; }
}
and here is my SignUp model :
public class SignUpModel
{
[Key]
public int id { get; set; }
[EmailAddress(ErrorMessage = "Invalid Email!")]
public string email { get; set; }
}
and this in my dbset:
public class Context : DbContext
{
public DbSet<NotActivatedUser> notActivatedUser { get; set; }
}
My problem is " How to use my SignUp model to insert into NotActivatedUsers Dbset?
I tried this :
public class AccountController : Controller
{
private Context db = new Context();
[HttpPost]
[AllowAnonymous]
public ActionResult SignUp(SignUpModel signUpModel)
{
if (ModelState.IsValid)
{
db.notActivatedUser.Add(signUpModel);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(signUpModel);
}
[AllowAnonymous]
public ActionResult SignUp()
{
return View();
}
}

ASP.NET MVC5 custom json model binder with html content

I used the FromJsonAttribute (created by Steve Sanderson), it's quite great, but sadly it doesn't pay attention to the AllowHtml attribute. I have the following model:
public class HKNewsPaperViewModel
{
public int Id { get; set; }
public string UserId { get; set; }
public string UserName { get; set; }
public string RPublisher { get; set; }
public string REditor { get; set; }
public string Title { get; set; }
public bool IsDraft { get; set; }
public bool IsNew { get; set; }
public List<HKNewsItemViewModel> NewsItems { get; set; }
public HKNewsPaperViewModel()
{
NewsItems = new List<HKNewsItemViewModel>();
}
}
public class HKNewsItemViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public string Link { get; set; }
[AllowHtml]
public string Body { get; set; }
}
In my controller I receive data this way:
[HttpPost]
public ActionResult New([FromJson] HKNewsPaperViewModel model)
{
return View();
}
FromJson attribute looks like this:
public class FromJsonAttribute : CustomModelBinderAttribute
{
private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer();
public override IModelBinder GetBinder()
{
return new JsonModelBinder();
}
private class JsonModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
if (string.IsNullOrEmpty(stringified))
return null;
return serializer.Deserialize(stringified, bindingContext.ModelType);
}
}
}
My problem is that I can't pass html content where the AllowHtml attribute is there. Thanks a lot!

Resources