v8::Object::SetAccessor - How does it work? - v8

There's no documentation on "v8::Object::SetAccessor" - is it correct to assume I can set a different setter and getter function for each specified property name? How does this affect the object if it was created from an object template? (yes, I know I can set it on a template, I'm just curious about possible conflicts)

Related

How to set the culture of all ValueProviderResult used in model binding to a given value?

It turns out that MVC's DefaultModelBinder uses different cultures in order to parse values (e.g. double, DateTime, etc.) for POST vs GET requests.
Here is more info.
I see that this is controlled by the Culture property of ValueProviderResult objects, which are returned from IValueProvider.GetValue().
My question is: How can I globally make sure that this value is always CultureInfo.InvariantCulture.
I know I can implement custom value providers and do it this way.
I know I can implement custom model binders and do it this way.
I know I can set the culture in the thread, but unfortunately this is not an option in my case.
What I am looking for is a way to set it so that even the default model binder and the existing value providers are able to parse in culture invariant way, irrespective of what the thread culture is set to.
As far as I know, there is no way that will match your criteria. You will have to do one of the things you know you can do (I'd say the most proper way would be a custom value provider).
Reason: All the default ValueProviders are hardcoded to use either CultureInfo.InvariantCulture or CultureInfo.CurrentCulture.
Here, specifically, is the way FormValueProvider does it:
internal FormValueProvider(
ControllerContext controllerContext,
IUnvalidatedRequestValues unvalidatedValues
)
: base(
controllerContext.HttpContext.Request.Form,
unvalidatedValues.Form,
CultureInfo.CurrentCulture // <--- Grrr, argh
)
{
}
The culture isn't retrieved from anywhere else (i.e., the argument above isn't used as a default, but as the one culture to use).
Cultures of the different IValueProviders
For reference, these are the cultures for each of the default IValueProviders:
ChildActionValueProvider: InvariantCulture
FormValueProvider: CurrentCulture
JsonValueProvider: CurrentCulture
RouteDataValueProvider: InvariantCulture
QueryStringValueProvider: InvariantCulture
HttpFileCollectionValueProvider: InvariantCulture
Replacing the CurrentCulture IValueProviders
It isn't a huge task to replace FormValueProvider, since, as seen above, it just calls its base class' (NameValueCollectionValueProvider) constructor - which takes the desired culture as an argument.
The original implementation of FormValueProvider appears on the surface to be harder than it actually is, with references to internal classes and interfaces. But they're not needed in order to replace the provider - they're only there for unit testing.
You only need to call the base constructor (as mentioned above), passing two NameValueCollections that are easy to acquire: Request.Forms and the Forms property of Validation.Unvalidated(Request) (a static method). And set the third argument to the culture you want.
The FormValueProviderFactory is even more straightforward.
JsonValueProvider is a bit more involved - basically you'd have to copy the source of JsonValueProviderFactory to a new class and modify it - because although it allows overriding GetValueProvider(), that method mainly consists of calls to other private static methods.
EDIT (Petar Ivanov): This worked for me. In order to make it work it was not enough to add the custom factory to ValueProviderFactories.Factories, because this way it's is added after the FormValueProviderFactory. Instead, I had to replace the FormValueProviderFactory with the custom one.

Modify Getter and Setter with Database First Approach

I'm currently learning ASP.Net MVC 3 with Entity Framework and want to know if there's a way to modify getter and setter for the model class generated by using the database first approach. Say, I want to sanitize HTML in the model's getter and setter to make sure there's no invalid code get saved in database. What's the best way to do that?
Thanks before.
You will want to use your custom validation routine. The class will be populated automatically, its up to you to determine then if its valid or not.
Use IValidateableObject or override the ValidateEntity method to handle your own validatations.
See Julie's article at:
http://msdn.microsoft.com/en-us/data/gg193959.aspx
In the edmx diagram you can edit the properties of a, well, property, one of which is the access modifier:

I'm creating a ModelBinder. What do I do to change the way it binds the property from the model back to the client on EditorFor?

I've learned how to create a custom ModelBinder that successfully changes the way the properties are set as parameters of my controller actions.
Now how do I intervene the inverse way? changing the way it sets the property back from the model to the View in the EditorFor method?
You can use Default Templates.
This is basically a snippet of code that is used for the type. It needs to be in the Views\Shared\DisplayTemplates and Views\Shared\EditorTemplates.
Name of the view needs to be name of the Class.
This way you may change DateTime and other basic types as well.

Is there a reason why the default modelbinder doesn't bind to fields?

I'm using ASP.NET MVC3 and i'm wondering that the default modelbinder binds to public properties but not to public fields.
Normally i just define the model classes with properties but sometimes i use some predefined classes which contains some fields. And everytime i have to debug and remember that the modelbinder just don't like fields.
The question: Whats the reason behind it?
but sometimes i use some predefined classes which contains some fields
While I cannot answer your question about the exact reason why the default model binder works only with properties (my guess is that it respects better encapsulation this way and avoids modifying internal state of the object which is what fields represent) I can say that what you call predefined classes should normally be view models. You should always use view models to and from your controller actions. Those view models are classes that are specifically defined to meet the requirements of the given view.
So back to the main point: fields are supposed to be modified only from within the given class. They should not be accessed directly from the outside. They represent and hold internal state of the class. Properties on the other hand is what should be exposed to the outside world. Imagine that in the property getter/setter you had some custom logic. By modifying directly the field this custom logic would be broken and potentially bring the object into an inconsistent state.
Maybe the reason for ignoring fields is to increase performance of the binder. Instead of searching all the Fields and properties. The Model Binder search for Properties only.
Though I think the Model Binder use cache to improve performance.
DefaultModelBinder exposes a public method:
DefaultModelBinder.BindModel, and a number of protected method available for overriding. All of them listed here.
Besides the model, these method refer to properties only, not fields, like
GetModelProperties,
GetFilteredModelProperties,
GetPropertyValue,
OnXYZValidating,
OnXYZValidated,
OnXYZUpdating,
OnXYZUpdated,
GetXYZValue,
where XYZ stands for either Model, or Property/ies, or both, and so on.
As you can see there is no Fields mentioned with these names whatsoever. As Darin explained no direct changes to Model's state are tolerated by the Binder. Hence no Field in its methods.
And also, you may wish to take a look at another important class: ModelBindingContext. An instance of this class gets passed to the BindModel, and subsequently to BindSimpleModel, and BindComplexModel, depending on model type (string, int,... are considered simple, everything else is complex).
So, this context has the following properties:
ModelXYZ, and
PropertyXYZ.
In other words you have no means to reference the fields in your ViewModel unless you do not override these classes and undertake special actions to do so.
But again, beware of fighting the framework, its always easier to follow it instead.
EDIT: The ModelMetadata class holds all the data needed to bind the model. Its code however, shows no sign of fields, field names, etc. Only properties are referenced and accessed. So, even if you try to inherit and override DefaultModelBinder and ModelBinderContext, you still won't be able to access fiellds, nevermind what their access modifier is: public, private, etc.
Hope this explains most of it.

Why would you bind the value of a NSProgressIndicator?

What's the point of binding the value of a NSProgressIndicator to your controller? It never seems to ask the controller for the value, except on startup. The only way to move the NSProgressIndicator seems to be by sending it #increaseBy:, which bypasses my binding. So, why would I bind?!
If your UI's bound value not updating, that means you either bungled the binding or your controller code is not modifying the bound value in a key-value-observing–compliant way. The most common problem is doing fooIvar = val rather than [self setFooIvar:val] or self.fooIvar = val.
Apple's answer to your problem:
[What to do if] Changing the value of a model property programmatically is not reflected in the user interface
If changes made to a model value programmatically are not being reflected in the user interface, this typically indicates that the model object is not key-value-observing compliant for the property, or that you are modifying the value in a manner that is bypassing key-value observing. You should ensure that:
The model class has automatic key-value observing enabled or implements manual key-value observing for the property.
That you are changing the value using an accessor method, or using a key-value-coding compliant method. Changing the value of an instance variable directly does not provide key-value observing change notifications.
If your model property is a collection, that you're modifying the content in a key-value-observing compliant manner. See “My collection controller isn’t displaying the current data” for more information.
For that answer and answers other common problems, see "Troubleshooting Cocoa Bindings."
You should also look at the examples provided by mmalc. They are a valuable resource.

Resources