I have a MVC 3 project that uses Entity Framework. I can successfully update entities like this:
[HttpPost]
publiv RedirectResult Update(MyEntity entity)
{
if(ModelState.IsValid)
{
this.entityRepository.Update(entity);
return RedirectResult(".../Admin");
}
return RedirectResult(".../UnssuccessfullOperation");
}
Now the problem arised when I added DateTime property to my entities. If I do not add the #Html.HiddenFor for my DateTime property the date of my entity is 01.01.0001 (or DateTime.Min), which obviously cannot be saved to the database. If I add the hidden input the date is rendered but on update my ModelState is not valid and I guess this is due to the fact that the datetime is passed as a string.
Now there is one solution, but it seems a little strange - to not render Html.Hidden in the view and to use the datetime from the entityRepository like this:
entity.DateSomething = this.entityRepository.GetSingle(entity.ID).DateSomething;
but it does not seem very correct. Are there any other better options in that case?
If I add the hidden input the date is rendered but on update my
ModelState is not valid and I guess this is due to the fact that the
datetime is passed as a string.
No, I suspect that it's due to the culture setting in your application and the datetime format used in the hidden field. They probably don't match.
Take a look at the following blog post which covers the different issues that arise when parsing dates and how the format will depend on whether you are doing a GET or POST request and also a possibility to write a custom model binder to use a fixed format for dates.
Related
Is it possible to have the Help Page sample generator ignore certain properties of a particular type?
For example, we use the same DTO for object Request and Response messages, for both POST and PUT requests. When user is POSTing a model (creating a new record) they don't need to provide the ID field.
But once its created and we serialize the new record into the response body, the ID field is included and returned to the client.
So in the POST request sample, I don't want the ID field to be displayed because for post request it doesn't make sense.
But the POST response sample, I do want the ID field displayed...
I am aware that there is the ApiExplorerSettings attribute which can be applied to a Class or Method...but is there anything similar for a Property?
Something like this would be great:
public class MyDTO
{
[ApiExplorerSettings(IgnoreForRequestApi = true, IgnoreForResponseApi = false)]
public int Id { get; set; }
// Other properties omitted for brevity...
}
Using the following annotation I've successfully hidden a property from the generation!
[ApiExplorerSettings(IgnoreApi = true)]
No, there isn't a similar option for a property. HelpPage uses formatter instances configured on the application to serialize the samples and as you can imagine the formatters must not have this knowledge within themselves.
Regarding workarounds:
a. You could explicitly set the raw sample for a particular action's requestsample via the SetSampleRequest extension of HttpRequestMessage. You should be able to see some examples about this in the file at *Areas\HelpPage\App_Start\HelpPageConfig.cs*.
b. In the file Areas\HelpPage\SampleGeneration\HelpPageSampleGenerator.cs, there is a method called WriteSampleObjectUsingFormatter which uses the application's formatter instances to write the samples. Here you would need to create new formatter instances having similar settings as your normal application has(so that they reflect the exact serialization/deserialization semantics that your application would normally react to when actual requests are made) and then try to hide the properties which you want to. We want to create new instances because we do not want to disturb the normal functioning of the application.
Example: In case of Json, you could create a new Json formatter instance and provide a ContractResolver which can hide the properties. Check this link: http://james.newtonking.com/projects/json/help/html/ConditionalProperties.htm
In case of Xml, I am not sure how we can hide properties without using the IgnoreDataMember attribute and also being non-intrusive.
Currently I would prefer option 'a' as its comparatively a simple workaround than 'b'.
ASP.NET WEB API uses Json.NET for JSON and DataContarctSerailizer for XML formatting so if you add [JsonIgnore] annotations over properties that you do not want included in your serialization should work just fine.
I have a model and a form in the view. I have a simple field of string which is called description. I'm able to insert scripts like: <script>alert('xss')</script> to that field.
I can see that in other actions on my site with other models I can't
I do not have an AllowHtml or anything like that.
the only difference is that for this model I use a post with a json object and content-type of application/json
the ModelState.IsValid is returning true. even though there is a description property with an xss script on it...
and for the other actions I make a simple ajax post.
why isn't the validation input work on this kind of JSON ajax posts?
how can I prevent xss across the entire site for this kind of ajax requests?
thanks
It is because ValidateInput is only for FormValueProvider. As for JsonValueProvider, you need to roll out your own mechanism.
Steps
1) Create a marker attribute CustomAntiXssAttribute
2) Create a custom model binder by sub-classing DefaultModelBinder
3) Overrides BindProperty method -> get the attempted value for the underlying property, sanitize it and assign it to the view model property.
Check this out.
Edited:
Replace the line var valueResult = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name); with var valueResult = bindingContext.ValueProvider.GetValue((string.IsNullOrWhiteSpace(bindingContext.ModelName) ? string.Empty : bindingContext.ModelName + ".") + propertyDescriptor.Name); in order to support nested ViewModel.
try using AntiXssLibrary from Nuget, and by using getSafeHtmlContent. you can get the safe content while you're saving your records to db.
Another approach is to use a Sanitizer library like this one, you can choose which HTML tags you want to be filtered out.
I have users selecting a DateTime using a caldendar/clock popup that allows them to make a selection. However, if they were to go in and edit the date to read something like: 6/12/201 10:36:47 AM instead of 6/12/2012 10:36:47 AM my Action gets past the ModelState.IsValid check and I get an error when the Controller attempts to save the object to the database (rightly so).
How do I properly validate DateTime in this situation? (I want to prevent a user from even being able to 'submit' the form if the datetime is not properly formatted)
Note: I currently have in place jquery.validate and typically (fields not DateTime) I use #Html.ValidationMessageFor(model => model.Field) - This does not appear to do anything for my current DateTime fields when they are formatted inappropriately.
you can simply add date client side validator for you DateTime field using snipet like that:
$(element).rules('add', {
date: true,
});
where "element" is your input for DateTime field.
Are you sure you're importing all of the requisite validation js files? it sounds like your server validation is working OK but the client is doing nothing. I suggest reading the following post by Brad Wilson: link
I have a Form in an MVC3 project. One of my input fields should accept HTML. Unfortunately I cannot have a ViewModel which this value maps to. The Field is autogenerated and read in automatically. I am getting the following error.
A potentially dangerous Request.Form value was detected from the client
Since there is no viewmodel, I cannot apply the [AllowHTML] attribute. Does anyone know a workaround that does not involve disabling validation for the entire page?
Thank You
Additional Information:
I can access the unvalidated value by doing the following:
using System.Web.WebPages;
using System.Web.Helpers;
.....Inside Controller....
string value = Request.Unvalidated("input-40");
The problem now is that the Request.Params collection throws an exception. I would like to access all the other values and have them be validated...just not that one. Is there a way for me to validate the other fields either explicitly or access a validated collection.
The following would be fine
string value = System.Web.Something.ValidateInput(Request.Unvalidated("input-41"));
Unfortunately I don't know where/if this method exists
You can try the ValidateInput(false) attribute:
[ValidateInput(false)]
public ActionResult YourAction(FormCollection yourCollection)
{
// your stuff
}
Use ValidateInput attribute for your action method. Seems to be unsafe but should work, cannot test it now.
I have a data entity that I use in two ways, I populate a table with some of its data when the page loads, and when you click a row of that column, I AJAX up the details of that item and display them in form fields. I'm using Spring-Roo generated REST endpoints on the server side, and Backbone.js on the client.
When the table loads, date fields have the format I expect, coming straight out of my MySQL database ("yyyy-MM-dd"). When I get my AJAX data, date fields come to me as Unix time values (e.g. "1323666000000").
I can convert that on the client side, but that's stupid. Any idea how I can get my json controller to not do this?
I've tried pushing those fields into my .java file and messing with the #DateTimeFormat annotation, but I can't see that makes any difference.
You can transform the date to any format you want for your JSON response.
In your case, you've been using the default JSON date transformer all the time for the java.util.Date type fields. This is basically what gets generated for you by the Spring Roo. Take a look and in your *_Roo_Json aspects and you will find smth. like this:
public java.lang.String PizzaOrder.toJson() {
return new JSONSerializer().exclude("*.class").serialize(this);
}
Such an implementation uses the flexjson.transformer.BasicDateTransformer class to transform the date for you. It is implemented like this:
public class BasicDateTransformer extends AbstractTransformer {
public void transform(Object object) {
getContext().write(String.valueOf(((Date) object).getTime()));
}
}
What you want is to use a different, more powerfull transformer. Luckily it comes with your Roo and it's called flexjson.transformer.DateTransformer. Now, in order to format your dates properly, just replace the default with the new transformer e.g. like this:
public java.lang.String PizzaOrder.toJson() {
return new JSONSerializer().exclude("*.class")
.transform(new DateTransformer("MM/dd/yyyy"), Date.class)
.serialize(this);
}
That's all :-)
Know that you may also apply different Date (and not only) transformations for different fields like this:
transform(new DateTransformer("MM/dd/yyyy"), "person.birthday")
For more info about the flexjson take a look at FLEXJSON project page.