I am simply calling an API and passing an object as a parameter and everything works fine. But then i wanted to validate the model before going any further so i simply wrote [Required] above the fields i always wanted filled.
MODEL
public class Consent
{
public Consent()
{
}
public int Id { get; set; }
[Required]
public int FacilityId { get; set; }
public string Heading { get; set; }
public string Description { get; set; }
}
and validate the model state in controller like this
public ActionResult<int> AddConsent(Consent consent)
{
if(!ModelState.IsValid){
throw new CustomException("000-0000-000", "Validation failed");
}
//Further Code
}
By this i expected model state to be false when i don't send the facilityId when i call the api
JSON
{
"heading": "HeadingFromPostman5",
"description": "DiscriptiomFromPostman5"
}
but its still true . I know .Net core is allocating 0 to int value when null but how can i validate it then? Whats the work around for this?
Simply replace this line:
[Required]
public int FacilityId { get; set; }
With this:
[Required]
public int? FacilityId { get; set; }
The Required attribute works well for nullable reference objects. For primitives, when an instance is created, the default value (in this case 0 for int) is assigned for FacilityId, and hence the Required won't work. If you make the FacilityId as nullable int then the Required attribute will work fine.
[Required]
public int? FacilityId { get; set; }
Related
I'm trying to make a field mandatory before submitting to the server. For this I used the [Required] data annotation for the model validation. It work as expected for the string data types but not for a double.
For some reason it's not working for the double type property.
Here is the code that I have for the model:
public class ProductMetadata
{
[Required]
public string Barcode { get; set; }
[StringLength(50)]
[Required(AllowEmptyStrings = false, ErrorMessage="Please insert the product name!")]
public string Name { get; set; }
[Range(0, 5000)]
public double ShippingCostPerUnit { get; set; }
[Range(0, 10000)]
public int QuantityForFreeShipping { get; set; }
public Nullable<int> CategoryId { get; set; }
public bool IsDeleted { get; set; }
[Range(0, 1000000)]
[Required(ErrorMessage="Please provide a unit price for the product!")]
public double UnitPrice { get; set; }
}
The response body is a JSON response and for none of the required fields completed has the following content:
{
"Message":"The request is invalid.",
"ModelState":
{"product":["Required property 'UnitPrice' not found in JSON. Path '', line 1, position 33."],
"product.Barcode":["The Barcode field is required."],
"product.Name":["Please insert the product name!"]
}
}
I don't understand why is working fine for the Name and Barcode and not for UnitPrice.
Edit 1:
If I remove the [Required] attribute and I put the input for the UnitPrice -1 I receive the appropriate validation message, so why is not working for the Required attribute?
Edit 2: The request payload(also updated the ProductMetadata class):
{IsDelete: false, CategoryId: 1}
CategoryId: 1
IsDelete: false
Any help is appreciated! Thanks!
The fastest decision is to make Unit Price nullable
[Range(0, 1000000)]
[Required(ErrorMessage="Please provide a unit price for the product!")]
public double? UnitPrice { get; set; }
The problem is the field Unit Price is missing in json and JSON Formatter tries to deserialize double and receives exception before Required is executed.
I know there are a couple of options to exclude/include some parameters in a modelview like using bind or using interfaces. However I have some problems when I am trying to implement nested IEnumerable variables. For example:
public class TestViewModel()
{
public int Id { get; set; }
public IEnumerable<Organisation> KPI { get; set; }
}
public class Organisation
{
public string Id { get; set; }
public string Name {get; set;}
public DateTime StartDate {get; set;}
public IEnumerable<Regiod> CategoryValues { get; set; }
}
public class Region
{
public System.Guid Id { get; set; }
public System.Int32 RegionId { get; set; }
public int Value { get; set; }
public System.String RegionName { get; set; }
}
[HttpGet]
public ActionResult edit(int id)
{
var model = new TestViewModel();
// Do something to populate the model
view(model)
}
In the view page (razor) all fields are disabled or hidden, except field Value in Region class and StartDate in Organization. My action Code is something like:
[HttpPost]
public ActionResult edit(TestViewModel model)
{
// Do something to populate the model
}
Everything works fine, unless somebody uses for example fiddler to set other disabled or hidden values, so those fields will be updated.
What I am after is to update just enabled fields and exclude the rest even somebody tries to set a value for them.
I tried bind[Exclude and Include], but my problem is I can bind 2 values from different classes. I tried UpdateModel(model, include) and it didn't work.
Any advice would be appreciated.
I have a strange issue that I can't wrap my head around. I am trying to create an "export to csv" function for my MVC4 application where the relevant JSON is passed via an ajax call to my ActionResult. The ActionResult deserializes the stringify'd JSON (with JSON.Net), writes it to a file in csv format, then returns the server path to the new file. My success callback then receives the path and calls the url to download.
This works fine locally, but on my live test server I get the following exception:
A circular reference was detected while serializing an object of type 'System.Reflection.RuntimeModule'.
The JSON (and subsequently the objects they are deserialized to) are slightly complex. They come from a grouped subset of a SlickGrid DataView. I was getting circular reference exceptions when I included the aggregate information for column totals (this is only relevant to those that are versed in SlickGrid, I do not believe the data being passed to the server is an issue), but I've removed them before passing the JSON to the server. Here is my JSON to C# class structure:
[Serializable]
public class Row
{
public int id { get; set; }
public DateTime DateCreated { get; set; }
public int RefNo { get; set; }
public string ClientName { get; set; }
public string Plate { get; set; }
public string Address1 { get; set; }
public int? ProductID { get; set; }
public string Product { get; set; }
public string S1 { get; set; }
public string S2 { get; set; }
}
[Serializable]
public class RootReportObject
{
public bool __group { get; set; }
public int level { get; set; }
public int count { get; set; }
public string value { get; set; }
public string title { get; set; }
public int collapsed { get; set; }
public List<Row> rows { get; set; }
public object groups { get; set; }
public string groupingKey { get; set; }
}
The only thing that I'm thinking is that, because of the way the data is structured, the List<> of rows in the root object may be throwing the circular references during deserializtion because a group does not necessarily have unique row references.
My question is why does it work fine locally?? I have no idea what I'm missing.
That's great that the [ScriptIgnore] attribute is helping. Also, something to be completely sure of is that all of your URL paths, including in your AJAX code, resolve correctly to the application root. When some of these are wrong, this is a notorious source of problems during the move from development to production.
It doesn't sound like it is necessarily the primary issue but I don't have any understanding of your app's design. It's definitely worth looking over.
I have a class department inheriting from activeentity
public class ActiveEntity : Entity, IActive
{
public ActiveEntity()
{
IsActive = true;
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public bool IsActive { get; set; }
[Timestamp, ScaffoldColumn(false), DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Computed)]
public Byte[] Timestamp { get; set; }
[ScaffoldColumn(false)]
public string CreationUserId { get; set; }
[ScaffoldColumn(false)]
public string LastModifiedUserId { get; set; }
}
public class Department:ActiveEntity
{
public Department()
{
this.Address = new DepartmentAddress();
}
[StringLength(9),MinLength(9),MaxLength(9)]
public string Name { get; set; }
public Guid ManagerId { get; set; }
[UIHint("AjaxDropdown")]
public User Manager { get; set; }
public Guid? AddressId { get; set; }
public DepartmentAddress Address { get; set; }
public ICollection<OverheadRate> OverheadRates { get; set; }
}
I am just using annotations no Fluent API. The data saves to the data Sql Server 2008 just fine however the address object never gets instantiated, even though I have the context use the include
return c.Set<Department>().Include(d => d.Address).Include(d => d.Manager).Where(predicate);
The data is returned I run sql profiler and then run the query it returns the correct data.
Any thoughts or suggestions?
Remove instantiating the address (this.Address = new DepartmentAddress();) in the Department constructor. Instantiating navigation references in the default constructor is evil and has nasty side effects like these:
What would cause the Entity Framework to save an unloaded (but lazy loadable) reference over existing data?
EF 4.1 Code First: Why is EF not setting this navigation property?
Is it possible to return nested classes in json with OpenRasta?
I'm using EF4.1 with code first (which in theory shouldn't make a difference, as they are just POCO classes).
Here is an example:
public class AppUser
{
[Key]
public int AppUserId { get; set; }
public string WinLogin { get; set; }
public string ScreenName { get; set; }
public string AgencyId { get; set; }
public virtual ICollection<UserAppVersion> UserAppVersion { get; set; }
}
public class UserAppVersion
{
[Key]
public int UaVersionId { get; set; }
public int AppUserId { get; set; }
public int AppVersionId { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
public virtual AppUser User { get; set; }
public virtual AppVersion Version { get; set; }
}
I try and return an AppUser record in json using this:
ResourceSpace.Has.ResourcesOfType<AppUser>()
.AtUri("/user").HandledBy<UserHandler>().AsJsonDataContract();
But I get an error:
System.Runtime.Serialization.SerializationException: Type 'System.Data.Entity.DynamicProxies.UserAppVersion_FD8D86F0A3AE39A0C370918637C1A90AD8D3ACA3E149677EA82C0A8D10ED0F8D' with data contract name 'UserAppVersion_FD8D86F0A3AE39A0C370918637C1A90AD8D3ACA3E149677EA82C0A8D10ED0F8D:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
Unfortunately I don't know how to resolve this. Any suggestions?
That's a data contract issue, not an openrast one.
The DataContract serialzier is seeing a dynamic proxy probably generated by EF code first, and when seeing that cannot render the object.
I'd recommend either swapping for another serialziation codec, or disabling transparent lazy loading, or alternatively marking your property as an ignore for serialziation and have another property typed to a List so the serializer can function.
See DataContractSerializer Error using Entity Framework 4.0 with WCF 4.0