locked
[Wordpress XML-RPC] Uploading an image to Wordpress RRS feed

  • Question

  • Hi everybody,

    I'm using the XML-RPC.net framework to upload an image to Wordpress through Wordpress' metaWeblog.newMediaObject.

    However, I'm stuck and keep running into the following error:

    CookComputing.XmlRpc.XmlRpcTypeMismatchException: response
    contains struct value where string expected (as type String)

    As the error suggests, something is wrong with my struct. But I can't find it. Do you have an suggestion?

    This is my code:

            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public struct Image
            {
                public string name;
                public string type;
                public string bits;
                public bool overwrite;
                public int gallery;
                public int image_d;
            }
    
            // Upload image
            public void UploadImage(string imageURL)
            {
                this.Url = wordpressXmlrpcUrl;
    
                Image theImage     = new Image();
                theImage.name      = "myNewImage.png";
                theImage.bits      = Base64Image(imageURL);
                theImage.overwrite = false;
                theImage.type      = "image/png";            
    
                try
                {
                    newImage("blogid", username, password, theImage, false);
                    Console.WriteLine("Image successfully uploaded!");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error: ", ex.ToString());
                    throw;
                }
            }
    
            [XmlRpcMethod("metaWeblog.newMediaObject")]
            public string newImage(string blogid, string username, string password, Image theImage, bool overwrite)
            {
                return (string)this.Invoke("newImage", new object[] { blogid, username, password, theImage, overwrite });
            }

    PS:

    • Posting a blog post with just text to Wordpress works (so url, password, login are correct).
    • The method (Base64Image) that returns a Base64 string of the image works correctly. I've verified that by using an online Base64 decoder with the output of that method.

    So, as I understand it, the problem lays not in what is send to Wordpress, but how it's send.

    Thanks in advance for any suggestion!


    • Edited by Jura4936 Saturday, August 10, 2013 12:08 PM Expanded first bullet point
    Saturday, August 10, 2013 12:06 PM

Answers

  • I think I've solved it! Thanks Dsmwb for pointing me in the right direction.

    This is what I had to change:

    1) As Dsmwb suggested, upload the raw byte[] data instead of the string.

    2) Instead of returning a string with..

    return (string)this.Invoke("newImage", new object[] { blogid, username, password, theImage, overwrite });

    I had to return an instance of the struct itself:

    return (Image)this.Invoke("newImage", new object[] { blogid, username, password, theImage, overwrite });

    Now the image gets uploaded correctly with no errors triggered.

    --------

    In case it's helpful to others, the full code is now:

            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public struct Image
            {
                public string name;
                public string type;
                public byte[] bits;
                public bool overwrite;
                public int gallery;
                public int image_d;
                public string url;            
            }
    
            // Upload image
            public void UploadImage(string imageURL)
            {
                this.Url = wordpressXmlrpcUrl;
    
                Image theImage      = new Image();
                theImage.name       = "myNewImage.png";
                theImage.bits       = Convert.FromBase64String(Base64Image(imageURL));
                theImage.overwrite  = false;
                theImage.type       = "image/png";            
    
                try
                {
                    Image uploadedImage = newImage("blogid", username, password, theImage, false);
    
                    Console.WriteLine("Uploaded to: {0}", uploadedImage.url);
                    Console.WriteLine("Image successfully uploaded!");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error:\n", ex);
                    throw;
                }
            }
    
            [XmlRpcMethod("metaWeblog.newMediaObject")]
            public Image newImage(string blogid, string username, string password, Image theImage, bool overwrite)
            {
                return (Image)this.Invoke("newImage", new object[] { blogid, username, password, theImage, overwrite });
            }
    • Marked as answer by Jura4936 Sunday, August 11, 2013 4:58 AM
    Sunday, August 11, 2013 4:57 AM

All replies

  • I think the problem is here:

    theImage.bits = Base64Image(imageURL);

    theImage.bits should contains the image raw data, but is seems you are assigning a file name (i.e., imageURL) to it...

    It should be:

    theImage.bits = Base64Image(File.ReadAllBytes(imageURL));

    Another possibile problem, theImage.name should be the same of the image you are uploading (or at least have the same extension):

    theImage.name =  Path.GetFileName(imageURL);

    or 

    theImage.name = "myNewImage" + Path.GetExtension(imageURL);



    • Edited by dsmwb Saturday, August 10, 2013 10:20 PM
    Saturday, August 10, 2013 9:38 PM
  • Thanks for replying Dsmwb!

    1) The 'Base64Image()' method returns a Base64 string from the image specified by the url. So no actual file name is assigned to 'theImage.bits'.

    If I, instead of sending a Base64 string, send a raw byte[] through (the two lines with the changed comment are the ones that are different from the code in the first post):

     [XmlRpcMissingMapping(MappingAction.Ignore)]
            public struct Image
            {
                public string name;
                public string type;
                public byte[] bits;     // ---> CHANGED
                public bool overwrite;
                public int gallery;
                public int image_d;
            }
    
            // Upload image
            public void UploadImage(string imageURL)
            {
                this.Url = wordpressXmlrpcUrl;
    
                Image theImage     = new Image();
                theImage.name      = "myNewImage.png";
                theImage.bits      = Convert.FromBase64String(Base64Image(imageURL));   // ---> CHANGED
                theImage.overwrite = false;
                theImage.type      = "image/png";            
    
                try
                {
                    newImage("blogid", username, password, theImage, false);
                    Console.WriteLine("Image successfully uploaded!");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error: ", ex.ToString());
                    throw;
                }
            }
    
            [XmlRpcMethod("metaWeblog.newMediaObject")]
            public string newImage(string blogid, string username, string password, Image theImage, bool overwrite)
            {
                return (string)this.Invoke("newImage", new object[] { blogid, username, password, theImage, overwrite });
            }

    ... I get the same error:

    Unhandled Exception: CookComputing.XmlRpc.XmlRpcTypeMismatchException: response
    contains struct value where string expected (as type String) [response]
    
       at CookComputing.XmlRpc.XmlRpcSerializer.ParseStruct(XmlNode node, Type value
    Type, ParseStack parseStack, MappingAction mappingAction)
       at CookComputing.XmlRpc.XmlRpcSerializer.ParseValue(XmlNode node, Type ValueT
    ype, ParseStack parseStack, MappingAction mappingAction, Type& ParsedType, Type&
     ParsedArrayType)
       at CookComputing.XmlRpc.XmlRpcSerializer.DeserializeResponse(XmlDocument xdoc
    , Type returnType)
       at CookComputing.XmlRpc.XmlRpcSerializer.DeserializeResponse(Stream stm, Type
     svcType)
       at CookComputing.XmlRpc.XmlRpcClientProtocol.ReadResponse(XmlRpcRequest req,
    WebResponse webResp, Stream respStm, Type returnType)
       at CookComputing.XmlRpc.XmlRpcClientProtocol.Invoke(Object clientObj, MethodI
    nfo mi, Object[] parameters)

    Furthermore, the line at which this happens is (according to the error message):

    return (string)this.Invoke("newImage", new object[] { blogid, username, password, theImage, overwrite });

    2) The image that is uploaded is of the same type (.png) than the image I'm trying to upload (.png). The original url contain a png image, and the 'Base64Image()' method save this image through:

    image.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
    If I decode the Base64 string and save that as a png file, it's identical to the original image, so I think it goes well.

    Sunday, August 11, 2013 4:26 AM
  • I think I've solved it! Thanks Dsmwb for pointing me in the right direction.

    This is what I had to change:

    1) As Dsmwb suggested, upload the raw byte[] data instead of the string.

    2) Instead of returning a string with..

    return (string)this.Invoke("newImage", new object[] { blogid, username, password, theImage, overwrite });

    I had to return an instance of the struct itself:

    return (Image)this.Invoke("newImage", new object[] { blogid, username, password, theImage, overwrite });

    Now the image gets uploaded correctly with no errors triggered.

    --------

    In case it's helpful to others, the full code is now:

            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public struct Image
            {
                public string name;
                public string type;
                public byte[] bits;
                public bool overwrite;
                public int gallery;
                public int image_d;
                public string url;            
            }
    
            // Upload image
            public void UploadImage(string imageURL)
            {
                this.Url = wordpressXmlrpcUrl;
    
                Image theImage      = new Image();
                theImage.name       = "myNewImage.png";
                theImage.bits       = Convert.FromBase64String(Base64Image(imageURL));
                theImage.overwrite  = false;
                theImage.type       = "image/png";            
    
                try
                {
                    Image uploadedImage = newImage("blogid", username, password, theImage, false);
    
                    Console.WriteLine("Uploaded to: {0}", uploadedImage.url);
                    Console.WriteLine("Image successfully uploaded!");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error:\n", ex);
                    throw;
                }
            }
    
            [XmlRpcMethod("metaWeblog.newMediaObject")]
            public Image newImage(string blogid, string username, string password, Image theImage, bool overwrite)
            {
                return (Image)this.Invoke("newImage", new object[] { blogid, username, password, theImage, overwrite });
            }
    • Marked as answer by Jura4936 Sunday, August 11, 2013 4:58 AM
    Sunday, August 11, 2013 4:57 AM
  • Hi, my name is Chris... I tried your code but some of the lines are underlined red. Would it be possible if you could help me on this? Im trying to upload image to wordpress and set it to featured image. 4 days straight trying and still no luck. Thank you very much.
    Friday, September 13, 2013 4:38 AM
  • Regarding the red lines, have you added a reference to the CookComputing dll build from the XML-RPC.net download? (http://xml-rpc.net/download.html)
    Friday, September 13, 2013 5:25 AM
  • OMG, thank you very much for your reply. yes i have sir... it's named CookComputing.XmlRpcV2.dll. would you mind if u send me a working sample? just the most basic code of uploading and setting an image as featured image. thank you very much.
    Friday, September 13, 2013 5:36 AM
  • I'm actually implementing this in vb.net, but c# code is okay as im also a c# programmer...Thank you very much. If this is okay with u :)
    Friday, September 13, 2013 5:41 AM
  • Please anyone?
    Friday, September 13, 2013 10:58 PM
  • Why don't you open a thread with the code you've already got? Surely, that cannot be that hard, you being a professional C# programmer and me a hobby programmer.
    Saturday, September 14, 2013 3:48 AM
  • Actually I'm not a professional programmer. But I do program. So we're basically on the same boat here :)
    Saturday, September 14, 2013 2:29 PM
  • Hi sir, I started a new thread here http://social.msdn.microsoft.com/Forums/vstudio/en-US/92320e9f-5b9b-481c-bbae-2d9873b47067/how-to-upload-image-to-wordpress-via-xmlrpc-communication-using-c-or-vbnet. Thank you very much :)
    Sunday, September 15, 2013 7:55 AM