Mono and Form Helper Selects - Invalid Cast

32 views
Skip to first unread message

bluesliverx

unread,
Jul 29, 2010, 7:19:46 PM7/29/10
to Castle Project Users
I've been butting my head against this problem for months now, and I
know that there aren't a lot of MonoRail + Mono users out there, but I
thought I would see if anyone has any ideas.

I'm using a pretty recent trunk version of MonoRail+ActiveRecord on
mono, and I've run into this on mono 2.4, 2.6, and now even the daily
tarball from yesterday (2.7 basically). It works fine on MS.NET. I
receive a System.InvalidCastException when running the form helper
select method on some activerecord objects. The objects are very
simple (basically an Id and a Name - shown below), but in certain
cases (and the cases seem random, but they are consistently on the
same objects) it is throwing this exception on mono.

Please help me! I feel like I'm missing something and just can't find
it.


Here is the full stack trace:

System.InvalidCastException: Cannot cast from source type to
destination type.
at
System.Reflection.MonoProperty.GetterAdapterFrame[SectionProxy,Int32]
(System.Reflection.Getter`2 getter, System.Object obj) [0x00000] in /
root/mono/build/mono-20100729/mcs/class/corlib/System.Reflection/
MonoProperty.cs:245
at System.Reflection.MonoProperty.GetValue (System.Object obj,
System.Object[] index) [0x00070] in /tmp/mono/build/mono-20100729/mcs/
class/corlib/System.Reflection/MonoProperty.cs:307
at Castle.MonoRail.Framework.Helpers.AbstractFormRelatedHelper
+ReflectionValueGetter.GetValue (System.Object instance) [0x00000] in
<filename unknown>:0
at
Castle.MonoRail.Framework.Helpers.DifferentTypeOperationState.CreateItemRepresentation
(System.Object current) [0x00000] in <filename unknown>:0
at Castle.MonoRail.Framework.Helpers.OperationState.get_Current ()
[0x00000] in <filename unknown>:0
at Castle.MonoRail.Framework.Helpers.FormHelper.GenerateSelect
(System.String target, System.Object selectedValue, IEnumerable
dataSource, IDictionary attributes) [0x00000] in <filename unknown>:0
at Castle.MonoRail.Framework.Helpers.FormHelper.Select
(System.String target, System.Object selectedValue, IEnumerable
dataSource, IDictionary attributes) [0x00000] in <filename unknown>:0
at CompiledViews.myviewname.Render () [0x00000] in <filename
unknown>:0
at Castle.MonoRail.Views.AspView.AspViewBase.Process () [0x00000] in
<filename unknown>:0
at Castle.MonoRail.Views.AspView.AspViewBase.GetContentViewContent
() [0x00000] in <filename unknown>:0
at Castle.MonoRail.Views.AspView.AspViewBase.Process () [0x00000] in
<filename unknown>:0
at Castle.MonoRail.Views.AspView.AspViewBase.GetContentViewContent
() [0x00000] in <filename unknown>:0
at Castle.MonoRail.Views.AspView.AspViewBase.Process () [0x00000] in
<filename unknown>:0
at Castle.MonoRail.Views.AspView.AspViewEngine.Process
(System.String templateName, System.IO.TextWriter output,
IEngineContext context, IController controller, IControllerContext
controllerContext) [0x00000] in <filename unknown>:0
at
Castle.MonoRail.Framework.Services.DefaultViewEngineManager.Process
(System.String templateName, System.IO.TextWriter output,
IEngineContext context, IController controller, IControllerContext
controllerContext) [0x00000] in <filename unknown>:0
at Castle.MonoRail.Framework.Controller.ProcessView () [0x00000] in
<filename unknown>:0
at mycontrollername.ProcessView () [0x00000] in <filename unknown>:
0
at Castle.MonoRail.Framework.Controller.RunActionAndRenderView ()
[0x00000] in <filename unknown>:0


Here is the Section model that the SectionProxy is being generated
from:

[ActiveRecord("sections",Lazy=true)]
public class Section : ActiveRecordValidationBase<Section> {
// Private variables
private int id;
private string name;

[PrimaryKey("id")]
public virtual int Id {
get { return id; }
set { id = value; }
}

[Property("name", NotNull=true)]
[ValidateNonEmpty("Please enter a name for the section")]
public virtual string Name {
get { return name; }
set { name = value.Trim(); }
}
}


And finally here is my view code generating the select:

<aspView:properties>
<%
IList<Section> sections = null;
%>
</aspView:properties>

<p><%=Helpers.Form.LabelFor("selectedSection", "Section:")%> <
%=Helpers.Form.Select("selectedSection", sections,
Helpers.Dict.CreateDict("text=Name", "value=Id", "firstoption=",
"firstoptionvalue=0"))%></p>

I have tried setting the selected value on the FormHelper.Select
method, but am having no luck whatsoever in finding what exactly is
going on. This view code is designed to have none selected (ie
selectedSection is a made up target which doesn't exist as an object),
but I have used other complex objects which try to set the properties
appropriately and sometimes succeed and sometimes throw exactly the
same error.
I should reiterate I think - it is consistently thrown on the same
objects (ie the object id is 17), but works fine for other values/
selections.

Thanks so much for all of your help!
-Brian

Daniel Quirk

unread,
Jul 30, 2010, 7:26:11 PM7/30/10
to Castle Project Users
Brian,

In the stacktrace you'll notice DifferentTypeOperationState, this
suggests the list contains more than one type of object. The exception
is therefore probably being caused by a section object being in the
cache due to another query having already been run in this request,
and so Nhibernate returns that object instead of fetching it again,
however this object is somehow a different type, ( base say, if you
were using tipe hierarchy) , and so cannot be cast. Try clearing the
session before you run your sections query and let me know how you get
on.

Cheers,

Dan

bluesliverx

unread,
Jul 31, 2010, 4:04:03 PM7/31/10
to Castle Project Users
Dan,

Thanks for the reply! I think you are exactly right with this. I've
dug a little more in the last couple of days and found it only happens
when I have another object with a Section object attached to it (in a
belongsto) that is loaded, and then the other section object is
loaded. The problem is, in the controller I am loading two
collections: the model with the attached Section object called
Application, and the collection of all Section objects. These are
lazy loaded by the way. When they are used with the FormHelper in the
view is when I actually receive the error. Also, neither of these
collections use a type hierarchy at all.

I also investigated further into the source code of mono and found
that the types involved were:
Cannot cast from source type 'Models.Section' to destination type
'Castle.Proxies.SectionProxy', so it looks like the Proxy was already
used/loaded and it is trying to cast to that I believe, or vice versa
I guess.

So my questions:
1) How do I clear the session in a way that still allows my lazy
loaded collections to load fine in the view? (I also couldn't find how
to easily clear the session besides using a new one, if you have a
quick tip on that, that would be great)
2) Why does this error only occur in mono and not in MS.NET? I know
you probably don't know this one off the top of your head. But do you
think this is a bug in mono I should investigate and try to report, or
something to do with the internals of ActiveRecord/NHibernate?

Thanks so much!
-Brian

bluesliverx

unread,
Aug 31, 2010, 2:29:14 PM8/31/10
to Castle Project Users
After sitting on this for awhile, I came back to it and found a
quick(ish) solution, although it involved modifying the Abstract Form
Helper source and recompiling monorail framework. I added a try/catch
InvalidCastException block in the ReflectionValueGetter.GetValue
method, so that the final code looked like this:

public override object GetValue(object instance)
{
try
{
try
{
return propInfo.GetValue(instance, null);
}
catch (InvalidCastException)
{
propInfo = propInfo.ReflectedType.BaseType.GetProperty(Name);
return propInfo.GetValue(instance, null);
}
}
catch (TargetException)
{
var tempProp = instance.GetType().GetProperty(Name);

if (tempProp == null)
{
throw;
}

return tempProp.GetValue(instance, null);
}
}

After recompiling, voila! No more invalid cast errors. Just thought I
would share the solution here if anyone was interested.

Thanks,
Brian

On Jul 31, 2:04 pm, bluesliverx <bksavi...@gmail.com> wrote:
> Dan,
>
> Thanks for the reply!  I think you are exactly right with this.  I've
> dug a little more in the last couple of days and found it only happens
> when I have another object with a Section object attached to it (in a
> belongsto) that is loaded, and then the other section object is
> loaded.  The problem is, in the controller I am loading two
> collections: the model with the attached Section object called
> Application, and the collection of all Section objects.  These are
> lazy loaded by the way.  When they are used with the FormHelper in the
> view is when I actually receive the error.  Also, neither of these
> collections use a type hierarchy at all.
>
> I also investigated further into the source code ofmonoand found
> that the types involved were:
> Cannot cast from source type 'Models.Section' to destination type
> 'Castle.Proxies.SectionProxy', so it looks like the Proxy was already
> used/loaded and it is trying to cast to that I believe, or vice versa
> I guess.
>
> So my questions:
> 1) How do I clear the session in a way that still allows my lazy
> loaded collections to load fine in the view? (I also couldn't find how
> to easily clear the session besides using a new one, if you have a
> quick tip on that, that would be great)
> 2) Why does this error only occur inmonoand not in MS.NET?  I know
> you probably don't know this one off the top of your head.  But do you
> think this is a bug inmonoI should investigate and try to report, or
> something to do with the internals of ActiveRecord/NHibernate?
>
> Thanks so much!
> -Brian
>
> On Jul 30, 5:26 pm, Daniel Quirk <danieljqu...@googlemail.com> wrote:
>
>
>
> > Brian,
>
> > In the stacktrace you'll notice DifferentTypeOperationState, this
> > suggests the list contains more than one type of object. The exception
> > is therefore probably being caused by a section object being in the
> > cache due to another query having already been run in this request,
> > and so Nhibernate returns that object instead of fetching it again,
> > however this object is somehow a different type, ( base say, if you
> > were using tipe hierarchy) , and so cannot be cast. Try clearing the
> > session before you run your sections query and let me know how you get
> > on.
>
> > Cheers,
>
> > Dan
>
> > On Jul 30, 12:19 am, bluesliverx <bksavi...@gmail.com> wrote:
>
> > > I've been butting my head against this problem for months now, and I
> > > know that there aren't a lot of MonoRail +Monousers out there, but I
> > > thought I would see if anyone has any ideas.
>
> > > I'm using a pretty recent trunk version of MonoRail+ActiveRecord on
> > >mono, and I've run into this onmono2.4, 2.6, and now even the daily
Reply all
Reply to author
Forward
0 new messages