Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Adding support for ModelBinderAttribute in core. #1633

Closed
wants to merge 1 commit into from

Conversation

harshgMSFT
Copy link
Contributor

This change introduces ModelBinderAttribute which can be used to specify a specific IModelBinder type or a specific IModelBinderProvider type. The attribute can also be used to provide a ModelNamePrefix. The attribute is allowed on types as well as parameters.
The "new" ModelBinderAttribute behaves in all respects like webapi except one.

  • There is no SuppressPrefixCheck property on the attribute in the current implementation. The rationale for this is as follows :
    SuppressPrefixCheck is Only applicable for the following case ( no binderType specified on parameter but a binder type of ModelBinder on the type.
// Notice no type is provided on the parameter's ModelBinder attribute.
void Action([ModelBinder] Person p);

// SuppressPrefixCheck only works if the binder type specified is of type IModelBinder 
// (and not IModelBinderProvider).
[ModelBinder(typeof(TestModelBinder), SuppresPrefixCheck=true)]
public class Person
{
}

What this results is before calling the TestModelBinder it will skip the check if there is a value provider which can provide a value.
IMHO this is a entirely unnecessary. @yishaigalatzer please share your thoughts.

@harshgMSFT
Copy link
Contributor Author

cc : @rynowak @dougbu @pranavkm

@harshgMSFT harshgMSFT force-pushed the MetadataProviderCleanup branch 2 times, most recently from 5ee8068 to 89b319a Compare November 25, 2014 06:12
@dougbu
Copy link
Member

dougbu commented Nov 25, 2014

would appreciate a high-level description of the change, preferably in the PR comment above. right now I see some refactoring, a new property or two, and lots of "custom" things. couldn't tell you what's being customized.

@harshgMSFT
Copy link
Contributor Author

@dougbu, I thought the code (with its detailed comments/summaries) was descriptive :) added a few comments in PR description. If this does not help lets sync offline.

/// Represents an <see cref="IModelBinder"/> which understands <see cref="ICustomModelBinderMetadata"/> and uses
/// the supplied <see cref="IModelBinder"/> bind the model.
/// </summary>
public class CustomModelBinder : MetadataAwareBinder<ICustomModelBinderMetadata>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm with @dougbu - not liking the naming. However this is all internal to the framework so it can be cleaned up whenever.

@rynowak
Copy link
Member

rynowak commented Nov 27, 2014

@rynowak rynowak changed the title Adding support for ModelMetadataAttribute in core. Adding support for ModelBinderAttribute in core. Dec 3, 2014
@rynowak rynowak force-pushed the ModelBindAttribute branch 3 times, most recently from 5dd3c34 to a9f0661 Compare December 4, 2014 00:18
@rynowak
Copy link
Member

rynowak commented Dec 4, 2014

@pranavkm updated

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert changes to this file.

@pranavkm
Copy link
Contributor

pranavkm commented Dec 4, 2014


public async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext.ModelMetadata.BinderType == null)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of doing this should this model binder derive from MetadataAwareModelBinder and follow the pattern which is already there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check would still be necessary though, to support a no op ModelBinderAttribute

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of doing this should this model binder derive from MetadataAwareModelBinder and follow the pattern which is already there?

This should work one of two ways (convince me that I'm wrong):

  1. The binder type is not part of model metadata and is instead part of some IBinderTypeBinderMetadata interface. This class only looks for a binder metadata and looks at the property on it.
  2. The binder type is part of model metadata. This class only looks at model metadata (my implementation)

The previous code in this PR mixed these two, and it's unnecessary coupling. It also breaks scenarios where a custom MMP sets a binder type.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose 2. above because I think it results in the best layering based on the current design.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only problem that I see in the current code is IBinderTypeProviderMetadata derives from IBinderMetadata which means that we are mixing 1 and 2. In the previous implementation ( my implementation ) there were two separate interfaces one for the type provider and one which inherited for IBinderMetadata.
Not sure I understand the reason for IBinderTypeProviderMetadata implementing IBinderMetadata when we are implementing option2.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will remove IBinderMetadata from it then.

Actually, this is needed too. The problem is that without this marker being an IBinderMetadata than webapi shim will do wierd things - like override the behavior you set via the attribute.

This is just a bigger issue of having all of the binding concerns be based on ModelMetadata. It's the design we have for now, but it's not great. We should revisit in the future.

@rynowak rynowak force-pushed the ModelBindAttribute branch 2 times, most recently from 9aa9256 to 60ff84e Compare December 4, 2014 22:44
@rynowak
Copy link
Member

rynowak commented Dec 5, 2014

@pranavkm updated please take a look.

Enabled [ModelBinder] on properties (for view models) and added a functional test for the same.

AttributeTargets.Parameter |

// Support properties on model DTOs.
AttributeTargets.Property |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yaay!

@pranavkm
Copy link
Contributor

pranavkm commented Dec 5, 2014

Looks good apart from comments. :shipit:

@rynowak rynowak closed this Dec 5, 2014
@rynowak rynowak deleted the ModelBindAttribute branch December 5, 2014 20:11
@@ -36,6 +37,12 @@ public CachedDataAnnotationsMetadataAttributes(IEnumerable<object> attributes)
}

/// <summary>
/// Gets (or sets in subclasses) <see cref="IEnumerable{IBinderTypeProviderMetadata}"/> found in collection passed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

teensy nit; is this a long line?

@dougbu
Copy link
Member

dougbu commented Dec 5, 2014

⌚ needs another PR adding the appropriate tests for new properties etc. in ModelMetadata hierarchy

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants