How to solve Serialization Error: ...Use XmlElementAttribute or XmlAttributeAttribute to specify a new name...

Hi guys:

I'm getting the following error message:
Member ParameterString.Val of type System.String hides base class member ParameterBase.Val of type System.Object. Use XmlElementAttribute or XmlAttributeAttribute to specify a new name.

The scenario: I have one base class, and two other that derive from it. I want to have a web service that deliver any of the two derived objects. Any help will be welcome on this idea.
The prolem right now is that I can't find the way to get rid of this error.
Following is my code, simple just to reproduce this error.

1- This is the Model class:

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

namespace WSAndXml_Model
{
      public abstract class ParameterBase
      {

            protected string _name;
            protected object _val;

            [XmlAttribute]
            public string Name
            {
                  get { return _name; }
                  set { _name = value; }
            }

            [XmlElement(ElementName = "ValObject")]
            public virtual object Val
            {
                  get { return _val; }
                  set { _val = value; }
            }
      }


      public class ParameterInt32 : ParameterBase
      {
            public ParameterInt32() : base()
            {}

            [XmlElement(DataType = "Int32", ElementName = "ValInt32")]
            public new Int32 Val
            {
                  get { return (Int32)_val; }
                  set { _val = value; }
            }
      }


      public class ParameterString : ParameterBase
      {
            public ParameterString() : base()
            {
            }

            [XmlElement(DataType = "string", ElementName = "ValString")]
            public new String Val
            {
                  get { return (String)_val; }
                  set { _val = value; }
            }
      }

}

2- This is the Web Service:
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

using System.Xml.Serialization;
using Model = WSAndXml_Model;


[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[XmlInclude(typeof(Model.ParameterBase))]
[XmlInclude(typeof(Model.ParameterInt32))]
[XmlInclude(typeof(Model.ParameterString))]
public class Parameters : System.Web.Services.WebService
{
      public Parameters()
      {    }

      [WebMethod]
      public Model.ParameterBase GetParameter()
      {
            Model.ParameterBase param = null;
            param = new Model.ParameterInt32();
            param.Name = "First";
            param.Val = 1;

            return param;
      }
}


3- This is the piece of code that access the web service:
      private void btnSubmit_Click(object sender, EventArgs e)
      {
            WSAndXmlRef.Parameters wsParam = new WSAndXmlRef.Parameters();

            WSAndXmlRef.ParameterBase param = null;
            param = wsParam.GetParameter();

            this.lblName.Text = param.Name;
            this.lblValue.Text = param.ValObject.ToString();
      }


Please help, thanks
Aishel
aishel73Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

corestruct00Commented:
Aishel,

it looks like you just need to make your derived class properties override the base class property (use the keyword override).

          [XmlElement(DataType = "Int32", ElementName = "ValInt32")]
          public override new Int32 Val
          {
               get { return (Int32)_val; }
               set { _val = value; }
          }

See the following: http://msdn2.microsoft.com/en-us/library/ebca9ah3(VS.80).aspx

corestruct00
aishel73Author Commented:
Actually I changed the line :
 [XmlElement(DataType = "Int32", ElementName = "ValInt32")]
for this other:
 [XmlElement(DataType = "int", ElementName = "ValInt32")]

but the code actually compiles ok. Is the web service while running that generates the error.
Anyway I change the "new" to "override" I get the following error: "cannot change return type when overriding inherited member", and the code won't compile.

Aishel
sumixCommented:
 either override or new, corestruct!

  and, of course, you cannot override a method and change its return type. The problem here is that you really need a new method.
OWASP Proactive Controls

Learn the most important control and control categories that every architect and developer should include in their projects.

aishel73Author Commented:
If I remove the val the serializer will work. But that is not my idea.
My idea was having a base element of Value type "object" to handle any unconvensional type, not defined in any of the subclases. This from th epoint of view of oop looks the right thing to do. Can you bring your thoughs on this.
The failing point is the serialization side.

Aishel
sumixCommented:
Here's what you can do:

   Modify the ParameterBase class like this:

    public abstract class ParameterBase
    {

        protected string _name;
        [XmlElement(ElementName="Val")]
        public object _val;

        [XmlAttribute]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        [XmlIgnore()]
        public virtual object Val
        {
            get { return _val; }
            set { _val = value; }
        }
    }

 This way, in your web service method (you have a local reference to Model assembly) you will see _val, Val (of type object) and Name properties. When sending the result of GetParameter method, 'param' object will be serialized (_val will be sent as an int with name 'Val' and Val will not be sent) and in Submit_Click method you will see for 'param' object Name and Val (of type int) properties.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
aishel73Author Commented:
Hi:

I get it, corect me if I'm wrong. It is not good that the serializer doesn't "understand" the new(C#)/shadows(VB) modifiers.
For the sake of clarity I end up with the following version:

      public class ParameterBase //abstract
      {
            protected string _name;
            protected object _val;

            [XmlAttribute]
            public string Name
            {
                  get { return _name; }
                  set { _name = value; }
            }

            [XmlIgnore()]
            public object Val
            {
                  get { return _val; }
                  set { _val = value; }
            }
            [XmlElement(ElementName="Val")]
            public object ValXml
            {
                  get { return _val; }
                  set { _val = value; }
            }
      }

Thanks all for your help.
Aishel
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.