Thursday, April 14, 2011

Confused on C# Array of objects and implicit type conversion

I am trying to pass an array of a simple object to a web service and I'm really stuck on this error during compile of my web client project:

Cannot implicitly convert type 'TRIMBrokerUtil.MetaData[]' to 'TRIMBrokerASMXProxy.ASMXProxy.MetaData[]'

Here is my "utility" project compiled into TRIMBrokerUtil.dll:

namespace TRIMBrokerUtil
{
    public class MetaData
    {
 protected string _Name;
 protected string _Value;
 public MetaData(string keyword, string setting) 
 {
     this.Name = keyword;
     this.Value = setting;
 }
 public string Name
 {
     get
     {
  return this._Name;
     }
     set
     {
  Name = value;
     }
 }
 public string Value
 {
     get
     {
  return this._Value;
     }
     set
     {
  _Value = value;
     }
 }
    }

Here is a snippet of the web service which also compiles fine: using TRIMBrokerUtil; namespace TRIMBrokerService { [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ToolboxItem(false)] public class FileService : System.Web.Services.WebService {

 [WebMethod]
 public string UploadFile(byte[] incomingArray
     , string FileName
     , long FileLengthInBytes
     , MetaData[] metaDataArray)
 {

...and usage later as this:

Update update = BuildMetaData(metaDataArray);

...and this:

private Update BuildMetaData(MetaData[] nvPairs)
{
    Update update = new Update();
    InputProperty[] ip = new InputProperty[nvPairs.Length];
    int i;
    for (i=0; i < nvPairs.Length; i++)
    {
 ip[i].Name = "udf:" + nvPairs[i].Name;
 ip[i].Val = nvPairs[i].Value;
    }
    update.Items = ip;
    return update;
}

Next, (via "Add Web Reference") I have my proxy class for the ASMX webservice in a separate project and it compiles without problem. Inside the generated reference.cs file I find this which seems OK:

    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/UploadFile", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    public string UploadFile([System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary")] byte[] incomingArray, string FileName, long FileLengthInBytes, MetaData[] metaDataArray) {
        object[] results = this.Invoke("UploadFile", new object[] {
                    incomingArray,
                    FileName,
                    FileLengthInBytes,
                    metaDataArray});
        return ((string)(results[0]));
    }

Now for the error that occurs in compilation in the web client project (default.aspx.cs):

    using TRIMBrokerUtil;

public partial class _Default : System.Web.UI.Page
{
    private void UploadFile(HttpPostedFile postedFile
       , string fileNameOnly
       , MetaData[] metaDataArray)
 {
     string strURI = string.Empty;
     TRIMBrokerASMXProxy.ASMXProxy.FileService client = new TRIMBrokerASMXProxy.ASMXProxy.FileService();
     BinaryReader b = new BinaryReader(postedFile.InputStream);
     byte[] binData = b.ReadBytes(numBytes);
     TRIMBrokerASMXProxy.ASMXProxy.MetaData[] kvData = metaDataArray; // error complains about this line
     strURI = client.UploadFile(binData, fileNameOnly, binData.Length, kvData );

I have also tried changing the last 2 lines above to simply this one line:

strURI = client.UploadFile(binData, fileNameOnly, binData.Length, metaDataArray);

...but that change introduces a 2nd error from the compiler which reads as:

The best overloaded method match for 'TRIMBrokerASMXProxy.ASMXProxy.FileService.UploadFile(byte[], string, long, TRIMBrokerASMXProxy.ASMXProxy.MetaData[])' has some invalid arguments

(note the original error about "cannot convert" is the 2nd error).

Sorry about being so verbose above. Hope you can help shed light on this confusion.

From stackoverflow
  • You are trying to assign an array of TRIMBrokerUtil.MetaData to an array of TRIMBrokerASMXProxy.ASMXProxy.MetaData. Remember that the asp.net proxy declares its own type.

    Just copy the data into a new array with the proxy type.

    John Galt : Freddy, not sure what you mean: "copy the data". A loop?
    eglasius : y, a loop, a linq with ToArray, any way to copy the data from the array to a new one with the current loop.
    John Galt : I barely know C# and I seem to have stumbled into something "advanced". Apparently my attempt to share a type definition between service and client is thwarted because proxy "declares its own type". So, I'll try to copy from my intended type to the proxy's type. Is there a better way to do this?
    eglasius : Y, sharing the type isn't supported directly by the asmx way of doing it. The new way (WCF) supports sharing the type, but as you are learning I would stick to the simple. Just avoid doing it in a way you need to share the types.
  • When you add a reference to the Web Service, Visual Studio will automatically generate code for the objects that are used as parameters to the functions of the web service. This is where your TRIMBrokerASMXProxy.ASMXProxy.MetaData class comes from.

    This is not the same as your TRIMBrokerUtil.MetaData class. You can remove the class from your TRIMBrokerUtil namespace and just use the one from the web service proxy instead.

0 comments:

Post a Comment