Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ProfileCommon -- casting in run-time fails

Summary: Null is returned after casting the base class to the derived class. However, the base class object seems to be OK before the casting.

Details: I am rewriting the older asp.net WebForms application to be able to extend it using MVC approach. As a part of the proces, I am converting the Web Site Project to the Web Application Project. In the case, the ProfileCommon class is not generated automatically. So, I have copied the autogenerated class definition from the older project and placed it as utils\ProfileCommon.cs. Content of the file is (simplified to a single property that was also renamed from the Czech equivalent):

using System;
using System.Web;
using System.Web.Profile;

namespace proj_app.utils
{
    public class ProfileCommon : System.Web.Profile.ProfileBase
    {
        public virtual string Name {
            get { return ((string)(this.GetPropertyValue("Name"))); }
            set { this.SetPropertyValue("Name", value); }
        }

        public static ProfileCommon GetProfile(string username)
        {
            return ((ProfileCommon)(ProfileBase.Create(username)));
        }
    }
}

The difference also is that I have removed the virtual from the GetProfile() method and made it static. (The ProfileBase does not have the GetProfile() method; so, it should be fine, right?)

The code compiles fine. However, I can observe the following in the browser (loosely translated, line numbers do not match with the example):

The object of the ProfileCommon type cannot be casted to proj_app.utils.ProfileCommon.
Description: ... unhandled exception during the web request...

Details about the exception: The object of the ProfileCommon type cannot be casted to proj_app.utils.ProfileCommon.

Zdrojová chyba:

Line 36:         public static ProfileCommon GetProfile(string username)
Line 37:         {
Line 38:             return ((ProfileCommon)(ProfileBase.Create(username)));
Line 39:         }
Line 40:     }


Source file: d:\__RizeniProjektu\aplikace\proj_app\utils\ProfileCommon.cs    Line: 38

Stack trace:
[InvalidCastException: Objekt typu ProfileCommon nelze přetypovat na typ proj_app.utils.ProfileCommon.]
   proj_app.utils.ProfileCommon.GetProfile(String username) in d:\__RizeniProjektu\aplikace\proj_app\utils\ProfileCommon.cs:38
   Users_seznam.Page_Load(Object sender, EventArgs e) in d:\__RizeniProjektu\aplikace\proj_app\Users\seznam.aspx.cs:29
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +51
   System.Web.UI.Control.OnLoad(EventArgs e) +92
   System.Web.UI.Control.LoadRecursive() +54
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772

When debugging, the ProfileBase.Create(username) returns the object, where the correct value for the Name property has the expected value (debugger knows how to get the value). However, after the cast, the resulting object reference is null. (I have to admit I am not very good in C#; I came from C++.) I tried also to split the command to get the ProfileBase p = ProfileBase.Create(username); (the object is not null), and only then to cast it to ProfileCommon q = p as ProfileCommon; (the q is null).

Update: Strange. I have renamed my class to ProfileComm, cleaned the project, compiled from scratch. There is no ProfileCommon string in the directory (nor in the sources, not in the binary files, the *.suo, the *.dll, the *.pdb, not in any other file). Even the filename was renamed to ProfileComm.cs not to have the ProfileCommon in the *.csproj. The source of the GetProfile() was changed to:

public class ProfileComm : System.Web.Profile.ProfileBase
{
    ...
    public static ProfileComm GetProfile(string username)
    {
        object p = ProfileBase.Create(username);
        Type t = p.GetType();
        string s = t.Name;

        return ((ProfileComm)(p));
    }
}

Now the details of the exception in the browser read (translated from another language): System.InvalidCastException: Object of the type ProfileCommon cannot be casted to the type proj_app.utils.ProfileComm.

When debugging, the debugger shows that the type of the p is ProfileCommon:

What the debugger shows about the type

I have no idea from where the type name ProfileCommon slipped in. Could it be related do a version of the .NET framework? What should I check? Could the ProfileCommon class still be generated dynamically somehow?

like image 625
pepr Avatar asked Jul 08 '15 13:07

pepr


2 Answers

ASP.NET automatically creates ProfileCommon class that inherits from ProfileBase on application start. If you want to use your own profile implementation you need to specify it explicitly in web.config. Something like:

<profile inherits="proj_app.utils.ProfileCommon">
....

This way ProfileBase.Create will return instance of your specified type instead of automatically generated one.

MSDN for more details

like image 45
Vitaliy Tsvayer Avatar answered Oct 14 '22 05:10

Vitaliy Tsvayer


It appears you have two types of ProfileCommon you should check your source to confirm this. You could also be more specific and have ProfileBase.Create(username) return proj_app.utils.ProfileCommon instead of just ProfileCommon.

Also for debugging maybe try and see what the compiler thinks the object really is, see this post: Could not resolve type: Issue while I am casting a custom class in c#


It seems you're conflicting with an ASP.NET class, I'd either create a new class entirely or create a super class of the ASP.NET ProfileCommon class.

ASP.NET uses the ProfileBase class to create the class used for the user profile. When an application that has the user profile enabled is started, ASP.NET creates a new class of type ProfileCommon, which inherits from the ProfileBase class. Strongly typed accessors are added to the ProfileCommon class for each property defined in the profile configuration section. The strongly typed accessors of the ProfileCommon class call the GetPropertyValue and SetPropertyValue methods of the ProfileBase base class to retrieve and set profile property values, respectively. An instance of the ProfileCommon class is set as the value of the Profile property for the ASP.NET application.

https://msdn.microsoft.com/en-us/library/system.web.profile.profilebase(v=vs.110).aspx

like image 189
Zach Leighton Avatar answered Oct 14 '22 05:10

Zach Leighton