My unit testing is failed when i change Required field to JsonRequired
my Dto Class
class name = customerDto
[JsonRequired]
public int ID {get; set;}
[JsonRequired]
public int Name{get; set;}
When use Required Attribute it was passed.
My Test Code
var data = new customerDto {ID = ValidID};
byte[] byteArray = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data));
httpContext.Request.Body = new MemoryStream(byteArray);
in above line debug will stop. i need to fix this.
My unit testing failed when i use JsonRequired Attribute. But it will successfully debug when i use Required attribute
Your customerDto is set to require the Name property to be given a value when converting to JSON. Your test converts the customerDto to JSON. Your test does not set a value on the Name property.
Either modify the test to supply a value to the Name property or remove the JsonRequired attribute from the Name property.
Your test does not do anything that would excercise the Required attribute. That's why you did not have problems when using that attribute.
Related
I have two endpoints in my ASP.net backend. One that takes an object with optional null parameters i.e. not required and also without any range checking so that this object can be stored in the database and a second that takes an ID of an object in the database. In this second endpoint I want to get the object out of the database and perform further validation. I.e. the user needs to have set all the optional values to be valid in range values for this second endpoint to work.
Basically I have two different endpoints that have the same data object but different validation needs.
eg
public class AnObject
{
[Required]
public Guid Id {get;set;}
public double? Foo {get;set;}
public double? Bar {get;set;}
}
with endpoint like this
[HttpPost]
public IActionResult Endpoint1([FromBody]AnObject anObject)
{
// if anObject is not valid (id is missing or incorrect types) ASP.net returns a BadRequest
// if ok add anObject to DB with id as key
}
and then a second object like this that has the same fields but non nullable and Required with Range checking.
public class AMoreStringentObject
{
[Required]
public Guid Id {get;set;}
[Required][Range(1,10)]
public double Foo {get;set;}
[Required][Range(1,10)]
public double Bar {get;set;}
}
and endpoint
[HttpPost]
public IActionResult Endpoint2(string id)
{
// get the AnObject from the DB with id matching parameter id
// now want to validate this using the AMoreStringentObject
}
in the second end point I would like get the AnObject from the database and perform validation using the DataAnnotations library. The second object and the first are not the same (nullable type on first) so I can't simply automap them. So i thought what I could do is serialize the AnObject to json and not write out things that are null, easy enough. So I want to then call the validation that must occur somewhere in the asp.net magic that would throw out error messages like "Foo is required". But how do I do that? i.e. validate the json string using the AMoreStringentObject so that the Required attributes throw a BadRequest with the required error. OR if there is a better way to go about this I'm all ears.
Additionally, I'm aware that I could do this with settings in the json deserializer but you get an unhelpful exception when you do this. I'd really like to get the BadRequest response that the Required field creates as this is a much more helpful message to the user. eg the json exception has a json position which is no use to the user because it is the backend that has serialized it.
I would recommend looking into FluentValidation which can be integrated into ASP.NET Core pipeline and will allow you to build reusable validations.
But if you want to use the build into the framework validation - you can look into Validator.TryValidateObject with manually created ValidationContext:
AMoreStringentObject toValidate = ...;
var vc = new ValidationContext(toValidate, serviceProvider: null, items: null);
var results = new List<ValidationResult>();
bool isValid = Validator.TryValidateObject(u, vc, results, true);
I have this schema for one of my DB documents:
public class InfoDoc
{
[JsonProperty(PropertyName = "documentId", NullValueHandling = NullValueHandling.Ignore)]
public string documentId {get; set;}
[JsonProperty(PropertyName = "creatorId", NullValueHandling = NullValueHandling.Ignore)]
public string creatorId{get; set;}
}
I have been using it for my application for a while now. I added a new property called creationTime but forgot to set DefaultValue attribute for it.
I also made the mistake of referencing the creationTime without initializing it. Not all the existing documents in the DB have that field populated. So I ran into null reference exceptions when using the web app.
Is there any Stylecop/code analyzer rule that I can leverage to ensure that such properties always have a default value and null value handling attributes set?
I'm using ASP.NET Core 2.0, and I have a request object annotated like this:
public class MyRequest
{
[Required]
public Guid Id { get; set; }
[Required]
public DateTime EndDateTimeUtc { get; set; }
[Required]
public DateTime StartDateTimeUtc { get; set; }
}
And in my controller:
public async Task<IActionResult> HandleRequest([FromBody] MyRequest request)
{ /* ... */ }
I noticed an issue with model binding: When I send a request containing the header Content-Type set to application/json and a an empty body, as I expect, the request in my controller is null and ModelState.IsValid is false.
But when I have a body like this:
{
"hello": "a-string-value!"
}
my request is NOT null, it has default values for everything, and ModelState.IsValid is true
This is happening of course while I'm missing all the Required properties, and the only existing one's name doesn't match a property there (even the type for this single parameter is string, which doesn't match any type on my model).
So in a way, those Required attributes seem to be working if there's nothing in my request, but they don't do anything if my request is not empty!
As I was preparing this question, I noticed that there's also a JsonRequired attribute, and it seems to take care of the properties being present.
So, what's the difference between Required and JsonRequired?
For correct work of Required attribute, you should make the properties nullable:
public class MyRequest
{
[Required]
public Guid? Id { get; set; }
[Required]
public DateTime? EndDateTimeUtc { get; set; }
[Required]
public DateTime? StartDateTimeUtc { get; set; }
}
Now if you send request with missing Id, EndDateTimeUtc or StartDateTimeUtc, corresponding field will be set to null, ModelState.IsValid will be set to false and ModelState will contain error(s) description, e.g. The EndDateTimeUtc field is required.
JsonRequired attribute is specific to JSON.Net. It plays during deserialization, while Required attribute (as other attributes from System.ComponentModel.DataAnnotations namespace) plays after model is deserialized, during model validation. If JsonRequired attribute is violated, the model will not be deserialized at all and corresponding action parameter will be set to null.
The main reason why you should prefer Required attribute over JsonRequired is that JsonRequired will not work for other content types (like XML). Required in its turn is universal since it's applied after the model is deserialized.
When you use [FromBody] as binding source, the Model properties will get default values and [BindRequired] will be ignored.
There is a related issue on "Problems with Parameter Validation".
In this case is better to use [JsonRequired] instead of [BindRequired] to enforce binding properties.
Note that [JsonRequired] affects serialization and deserialization both.
Yes, the difficulty is that if you choose Required, the semantics for the client of the web request change incorrectly - i.e. you are saying you can pass in a null, when you really need a proper value.
Using JsonRequired sorts this, but this is provided by NewtonSoft, so stops working when you upgrade to .Net Core 3. This is because .Net Core 3 uses its own Json parser instead of NewtonSoft.
I am using WCF and .NET 4.5, working with a WCF SOAP web service that's been in production for some time. Need to rename a property, but there is a small chance that some of production customers may have the old property name in their requests.
For example, if a property was called MyPoorlyNamedProperty and I renamed it to MyProperty, I wish both MyPoorlyNamedProperty and MyProperty in SOAP would de-serialize to that same property.
Is there a way to decorate a property of a type in WCF to specify an "alternative" accepted name for the renamed property?
I don't know any alternative name decoration or anything similar. If you wish to create a breaking-change, you need to do one of both:
Change the property name and notify your clients that the contract was changed and they need to prepare accordingly
Modify your API to accept both properties. In case it recieves a request with value for the old property, set this value to the new property.
Solution 2 is ugly and not the best practice. I don't recommend doing it.
You can add the second property to your model. And work with get; set; and the DataMember attribute.
[DataContract]
public class Person
{
[DataMember]
private string _surname;
public string Surname { get { return this._surname; } set { this._surname = value; } }
public string Lastname { get { return this._surname; } set { this._surname = value; } }
}
I need advice on how to return a limited set of data from an MVC controller.
Lets say I have a class that is constructed like so:
public interface ICustomerExpose
{
string Name {get; set;}
string State {get; set;}
}
public interface ICustomer: ICustomerExpose
{
int Id {get; set;}
string SSN {get; set;}
}
public class Customer: ICustomer
{
...
}
In my MVC project I have a controller action that returns customer data. The project is actually more like a web service as there is no View associated with the data... we use the XmlResult (provided by the MVCContrib project). The controller action looks like this:
// GET: /Customer/Show/5
public ActionResult Show(int id)
{
Customer customer = Customer.Load(id);
... // some validation work
return new XmlResult((ICustomerExpose)customer);
}
The above controller code does not work like I want it to. What I want to happen is that only the Name and State properties are serialized and returned in the XmlResult. In practice the whole customer object is serialized including the data I definitely don't want exposed.
I know the reason this doesn't work: you can't serialize an interface.
One idea floated around the office was to simply mark the properties Name and State as [XmlIgnore]. However, this doesn't seem like a good solution to me. There might be other instances where I want to serialize those properties and marking the properties on the class this way prohibits me.
What is the best way to achieve my goal of only serializing the properties in the ICustomerExpose interface?
Addendum:
For those interested in what XmlResult does here are the relevant parts of it:
public class XmlResult : ActionResult
{
private object _objectToSerialize;
public XmlResult(object objectToSerialize)
{
_objectToSerialize = objectToSerialize;
}
/// <summary>
/// Serialises the object that was passed into the constructor
/// to XML and writes the corresponding XML to the result stream.
/// </summary>
public override void ExecuteResult(ControllerContext context)
{
if (_objectToSerialize != null)
{
var xs = new XmlSerializer(_objectToSerialize.GetType());
context.HttpContext.Response.ContentType = "text/xml";
xs.Serialize(context.HttpContext.Response.Output, _objectToSerialize);
}
}
}
You can try this, however I am not sure if it works with xml serializers:
return new XmlResult(new { customer.Name, customer.State });
See this related question which recommends using an anonymous type.
// GET: /Customer/Show/5
public ActionResult Show(int id)
{
Customer customer = Customer.Load(id);
... // some validation work
var result = from c in cusomter
select new
{
Name = c.Name,
State = c.State,
};
// or just
var result = new
{
Name = customer.Name,
State = customer.State,
};
return new XmlResult(result);
}
Consider using, just for this one problem, XML literals in VB9 rather than serialization. Seriously. Just give it 20 minutes of your time. There's many options.
http://www.hanselman.com/blog/TheWeeklySourceCode30VBNETWithXMLLiteralsAsAViewEngineForASPNETMVC.aspx
http://www.hanselman.com/blog/XLINQToXMLSupportInVB9.aspx
http://blogs.msdn.com/dmitryr/archive/2008/12/29/asp-net-mvc-view-engine-using-vb-net-xml-literals.aspx
http://haacked.com/archive/2008/12/29/interesting-use-of-xml-literals-as-a-view-engine.aspx
http://www.infoq.com/news/2009/02/MVC-VB
For what you're doing, returning XML as a poor-man's Web Service, this is tailor-made.
I ended up just doing the XmlIgnore as co-workers suggested, even though this left me with some undesirable (or so I thought) behaviors.
To get around the fact that XmlIgnore would continue hiding properties that I might want serialized later I asked another question trying to find a way to around that issue. Cheeso came up with a great answer making the XmlIgnore the best route (in my opinion) to take.