ASP.net MVC v2 - Debugging Model Binding Issues - BUG? - asp.net

I am having more than a little difficulty trying to debug why MVC is not binding correctly in a given case I have...
Basically, I have my action which receives a complex object which in turn has a complex child object - Activity.Location.State (Where Activity is the complex object that the action expects, Location is a complex child object and State is just a string).
Now I set up a test project which as far as I can tell exactly mimics the actually scenario I have, in this test case the binding works... But in my actually project, the binding to Activity works but not to Location... By putting break points within the Locaiton property I can tell that MVC is retrieving the complex Location object from the Activity, but its not setting any of the properties...
I am trying to debug the issue but I need access to the MVC v2 preview 2 symbols which I can't seem to track down... I would like to see what it is actually doing once it pulls out the location object (for some reason I think it might be failing internally but swallowing the exception).
Any ideas on what I could do here...
Cheers
Anthony
UPDATE:
Ok I did what J.W. suggested and directly reference the MVC project...
I found the problem and there was one very small difference that I overlooked... As I result I found out that MVC does not currently support multiple levels of INTERFACE inheritance when it comes to model binding... See the following...
//MODEL
public class Location : ILocation
{
...
}
public interface ILocation : ILocationCore
{
...
}
public interface ILocationCore //In my sample I didn't have this second level interface
{
...
//MVC doesn't find any of these properties
...
}
public class Activity : IActivity
{
...
}
public interface IActivity : IActivityCore
{
ILocation Location { get; set; } //MVC finds this and reads its meta type as an ILocation
//Also the implementation of this Location within Activity will always return a instance - our IoC takes care of that, so MVC should never have to create the instance
}
public interface IActivityCore
{
...
}
//CONTROLLER
public ActionResult Create(Activity activity)
{
}
Hence what I have found is that MVC finds the Location and reads its meta type as an ILocation, but when GetModelProperties is run within the DefaultModelBinder the following occurs -
protected virtual PropertyDescriptorCollection GetModelProperties(ControllerContext controllerContext, ModelBindingContext bindingContext) {
return GetTypeDescriptor(controllerContext, bindingContext).GetProperties();
//This return no properties
}
protected virtual ICustomTypeDescriptor GetTypeDescriptor(ControllerContext controllerContext, ModelBindingContext bindingContext) {
return new AssociatedMetadataTypeTypeDescriptionProvider(bindingContext.ModelType).GetTypeDescriptor(bindingContext.ModelType);
//bindingContext.ModelType - is ILocation
}
Hence I am assuming at this point that TypeDescriptionProvider doesn't support this style of inheritance, which i am quite surprised by. Also looking at the v1 source it looks like this was introduced with v2 - but v1 mightn't have been able to support what I am trying to do anyway.
I wouldn't say that this is really a bug, but I tried replacing my the interfaces with concrete classes and it worked fine. Hence the behavior isn't really what I would expect and is a little inconsistent.
Any thoughts??? I would have thought that this inheritance was not fairly standard but would occur often enough to be catered for. Thanks for the reply.
Cheers

Turns out this behavior is by design due to how interface inheritance works. Interfaces do not define implementations, thus ILocation doesn't "inherit" the properties of ILocationSource. Rather, ILocation only defines what a concrete implementation must implement.
For the full details including the section of the CLI (Common Language Infrastructure) spec which defines this behavior, check out: http://haacked.com/archive/2009/11/10/interface-inheritance-esoterica.aspx

I would simply reference to the asp.net mvc2 source code published in codeplex. I did that, it's very straightforward.
It will give you much better understanding when you debugging through the source code.

Related

Mono.Cecil: Getting Method Reference from delegate passed as Generic Parameter

I'm trying to get an understanding of which concrete types are providing the implementations of interfaces in an IOC (dependency injection) container. My implementation works fine when there are no delegates involved. However, I'm having trouble when a delegate method is passed as the type factory, as I can't get Mono.Cecil to give me the concrete type or a method reference to the factory back. I'm specifically in this case trying to build a component that can work with the IServiceCollection container for .Net ASP.Net REST APIs. I've created a 'minimised' set of code below to make it easy to explain the problem.
Consider the following C# code:
interface IServiceProvider {}
interface IServiceCollection {}
class ServicesCollection : IServiceCollection {}
interface IMongoDBContext {}
class MongoDBContext : IMongoDBContext
{
public MongoDBContext(string configName) {}
}
static class Extensions
{
public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
{
return null;
}
}
class Foo
{
void Bar()
{
IServiceCollection services = new ServicesCollection();
services.AddSingleton<IMongoDBContext>(s => new MongoDBContext("mongodbConfig"));
}
}
When successfully locating the 'services.AddSingleton' as a MethodReference, I'm unable to see any reference to the MongoDBContext class, or its constructor. When printing all the instructions .ToString() I also cannot seem to see anything in the IL - I do see the numbered parameter as !!0, but that doesn't help if I can't resolve it to a type or to the factory method.
Does anyone have any ideas on how to solve this?
Most likely your code is looking in the wrong place.
C# compiler will try to cache the conversion of lambda expression -> delegate.
if you look in sharplab.io you'll see that the compiler is emitting an inner class '<>c' inside your Foo class and in that class it emits the method '<Bar>b__0_0' that will be passed as the delegate (see opcode ldftn).
I don't think there's an easy, non fragile way to find that method.
That said, one option would be to:
Find the AddSingleton() method call
From there start going back to the previous instructions trying to identify which one is pushing the value consumed in 1 (the safest way to do that would be to consider how each instruction you are visiting changes the stack). In the code I've linked, it would be IL_0021 (a dup) of Bar() method.
From there, do something similar to 2, but now looking for the instruction that pushes the method reference (a ldftn) used by the ctor of Func<T, R>; in the code linked, it would be IL_0016.
Now you can inspect the body (in the code linked, Foo/'<>c'::'<Bar>b__0_0')
Note that this implementation has some holes though; for instance, if you call AddSingleton() with a variable/parameter/field as I've done (services.AddSingleton(_func);) you'll need to chase the initialization of that to find the referenced method.
Interestingly, at some point Cecil project did support flow analysis (https://github.com/mono/cecil-old/tree/master/flowanalysis).
If you have access to the source code, I think it would be easier to use Roslyn to analyze it (instead of analyzing the assembly).

Getting IMetadataDetailsProviders to Run More than Once in ASP.NET Core

This is a tricky question which will require some deep knowledge of the ASP.NET Core framework. I'll first explain what is happening in our application in the MVC 3 implementation.
There was a complex requirement which needed to be solved involving the ModelMetaData for our ViewModels on a particular view. This is a highly configurable application. So, for one "Journal Type", a property may be mandatory, whereas for another, the exact same property may be non-mandatory. Moreover, it may be a radio-button for one "Journal Type" and a select list for another. As there was a huge number of combinations, mixing and matching for all these configuration options, it was not practical to create a separate ViewModel type for each and every possible permutation. So, there was one ViewModel type and the ModelMetaData was set on the properties of that type dynamically.
This was done by creating a custom ModelMetadataProvider (by inheriting DataAnnotationsModelMetadataProvider).
Smash-cut to now, where we are upgrading the application and writing the server stuff in ASP.NET Core. I have identified that implementing IDisplayMetadataProvider is the equivalent way of modifying Model Metadata in ASP.NET Core.
The problem is, the framework has caching built into it and any class which implements IDisplayMetadataProvider only runs once. I discovered this while debugging the ASP.NET Core framework and this comment confirms my finding. Our requirement will no longer be met with such caching, as the first time the ViewModel type is accessed, the MetadataDetailsProvider will run and the result will be cached. But, as mentioned above, owing to the highly dynamic configuration, I need it to run prior to every ModelBinding. Otherwise, we will not be able to take advantage of ModelState. The first time that endpoint is hit, the meta-data is set in stone for all future requests.
And we kinda need to leverage that recursive process of going through all the properties using reflection to set the meta-data, as we don't want to have to do that ourselves (a massive endeavour beyond my pay-scale).
So, if anyone thinks there's something in the new Core framework which I have missed, by all means let me know. Even if it is as simple as removing that caching feature of ModelBinders and IDisplayMetadataProviders (that is what I'll be looking into over the next couple of days by going through the ASP.NET source).
Model Metadata is cached due to performance considerations. Class DefaultModelMetadataProvider, which is default implementation of IModelMetadataProvider interface, is responsible for this caching. If your application logic requires that metadata is rebuilt on every request, you should substitute this implementation with your own.
You will make your life easier if you inherit your implementation from DefaultModelMetadataProvider and override bare minimum for achieving your goal. Seems like GetMetadataForType(Type modelType) should be enough:
public class CustomModelMetadataProvider : DefaultModelMetadataProvider
{
public CustomModelMetadataProvider(ICompositeMetadataDetailsProvider detailsProvider)
: base(detailsProvider)
{
}
public CustomModelMetadataProvider(ICompositeMetadataDetailsProvider detailsProvider, IOptions<MvcOptions> optionsAccessor)
: base(detailsProvider, optionsAccessor)
{
}
public override ModelMetadata GetMetadataForType(Type modelType)
{
// Optimization for intensively used System.Object
if (modelType == typeof(object))
{
return base.GetMetadataForType(modelType);
}
var identity = ModelMetadataIdentity.ForType(modelType);
DefaultMetadataDetails details = CreateTypeDetails(identity);
// This part contains the same logic as DefaultModelMetadata.DisplayMetadata property
// See https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadata.cs
var context = new DisplayMetadataProviderContext(identity, details.ModelAttributes);
// Here your implementation of IDisplayMetadataProvider will be called
DetailsProvider.CreateDisplayMetadata(context);
details.DisplayMetadata = context.DisplayMetadata;
return CreateModelMetadata(details);
}
}
To replace DefaultModelMetadataProvider with your CustomModelMetadataProvider add following in ConfigureServices():
services.AddSingleton<IModelMetadataProvider, CustomModelMetadataProvider>();

Custom Binding Required for SpringMVC Form Field

I ran into the following SpringMVC issue: there is a domain object which uses a certain Address sub-object, but the getters/setters have to be tweaked to use a different Address object via conversion. This is an architectural requirement.
public class DomainObj {
protected DomainObj.Address address;
public anotherpackage.new.Address getAddress()
{
return convertFrom(address);
}
public void setAddress (anotherpackage.new.Address value)
{
this.address = convertTo(value);
}
}
// Internal Address object, old, #1
public static class Address {
protected String street1;
protected String street2;
// etc., getters/setters
}
Now, in the JSP, I bind an Input Text Field to the new Address object (the result of conversions) that's what we have to deal with. In this new 2nd Address object (anotherpackage.new.Address), there is a field e.g. "addressLine1", which is different from the old object's "Street1":
<form:input path="topObject.address.addressLine1" />
My problem is that the setter, setAddress(), never gets called in this case for binding (verified in the Debugger). Any solutions to this?
Your options are:
a) do not bind directly to the business object
b) configure a binder to do the conversion to your domain object
Discussion:
Usually in enterprise class software we don't want to bind directly to the business objects -- which are usually entities (in the context of jpa). This is because session handling is a bee-otch. Usually we code against DTOs, and when one is received from the front-end we read the appropriate object from the repository (ORM) layer, update it, and save it back again (I've only described updates because they're the hardest, but a similar model works for everything).
However, spring mvc binders offer a way of binding anything to anything. They're a bit complicated and it'll take too long to explain here, but the docs are in the spring documentation and you want to be looing at converters and a conversion service. There are SO Q/A's on this topic, for example...

Fluorine TransientAttribute and Linq-to-SQL

I've found a workaround, but I had trouble earlier this week working with FluorineFx, where I had a Linq-to-SQL–generated object I wanted to send over the wire to Flash. This object contained a property that Flash didn't need:
[Association(Name="User_UserEntry", Storage="_UserEntries",
ThisKey="UserID", OtherKey="UserID")]
public EntitySet<UserEntry> UserEntries { ... }
But Flex couldn't handle reinflating this type, throwing:
ArgumentError: Error #2173: Unable to read object in stream. The class flex.messaging.io.ArrayCollection does not implement flash.utils.IExternalizable but is aliased to an externalizable class.
Now I didn't need to send the property over the wire, so I tried the steps that Marc Gravell suggested in issue 456624, firstly adding attributes to it using the MetadataTypeAttribute in System.ComponentModel.DataAnnotations (found from JasonW's comment on issue 393687:
[MetadataType(typeof(UserMetadata)]
public partial class User { }
internal class UserMetadata
{
[FluorineFx.Transient]
public EntitySet<UserEntry> UserEntries { get; set; }
}
Unfortunately it seems that FluorineFx doesn't support metadata attributes yet (which isn't very surprising, tbh, they are quite new).
What I ended up having to do was create a dedicated DTO, with all the properties that Flash cared about and none of the properties it didn't. Not the most elegant of solutions.
So, have other people come across this problem and have you found more-elegant ways of solving it?
I use the Transient attribute and it works fine. I do work with the latest FluorineFx release from SVN.

How can I improve our CM.AppSettings references

ASP.NET 3.5
Classes throughout our solution referenced ConfigurationManater.AppSettings[""] to get appSettings (from web.config).
We decided we weren't happy with that. Folks were mistyping appSetting key names in code (which compiled fine), and it was cumbersome to track usages. And then there's the duplicated strings throughout the codebase as you reference the same appSettings all over the place.
So, we decided that only one class would be allowed to reference the ConfigurationManager, and the rest of the solution would reference that class when it needed the value of a certain appSetting. ConfigurationManater.AppSettings[""] was static, so we exposed a bunch of static read-only properties off of our single Settings class.
public class Settings {
public static string Foo {
get {
return ConfigurationManager.AppSettings["Foo"];
}
}
}
That worked pretty well, until we needed to mock the settings in our tests. We created an interface to enable our mocking (was this a mistake of any kind?).
public interface ISettings {
string Foo {
get;
set;
}
}
public class Settings : ISettings {
public string Foo {
get {
return ConfigurationManager.AppSettings["Foo"];
}
}
}
And now we're injecting the ISettings instance as a dependency of the objects which use settings values (the class/interface are in a project that everyone can reference without problems).
In places where we can't inject an existing instance (e.g. Global.asax), we construct a new instance into a static field.
Given all of that, what would you recommend we change, and why?
Using an interface to represent configuration is a good idea. But your implementation looks a little off.
Joshua Flanagan wrote about writing application configuration code in a way that specific configuration sections can be injected into your code. This is a good idea, as it really decouples your code from worrying about details behind configuration. Have a read.
I think this will address the issue you are having re. testability.

Resources