0

I am trying to write a c# code by which I want to get a image from web api and the title of the image from the api. I implemented a method named GetImage and try to return two results (image and title) from it. However I wrote a code but as I am new handling this situation,I do not know what to do in this case.

My Image service class which contain the methods is-

public class ImageService
{
    public string GetImage(string name)
    {                
        string result1;
        string result2;

        using (WebClient client = new WebClient())
        {
            var uri = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=pageimages&pithumbsize=400&titles="+name;
            string requestUrl = string.Format(uri, name);
            var response = client.DownloadString(new Uri(uri));
            var responseJson = JsonConvert.DeserializeObject<ImgRootobject>(response);
            var firstKey = responseJson.query.pages.First().Key;
            result1 = responseJson.query.pages[firstKey].thumbnail.source;
            result2 = responseJson.query.pages[firstKey].title;

            var hash = uri.GetHashCode();

        }
        return result1,result2; //showing error
    }
}

Now the Form1.cs where i want to show results in picturebox and label is-

public partial class Form1 : Form
{
    private readonly ImageService _imageService;
    public Form1()
    {            
        _imageService = new ImageService();
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
        pictureBox1.LoadAsync(_imageService.GetImage(textBox1.Text));
        label1.Text = _imageService.GetImage(textBox1.Text);// not working
    }
}
Nowshin
  • 67
  • 1
  • 2
  • 11

8 Answers8

4

The best method is to create a new class that holds the details you need and return that. That way, if you need to add more information, you can just add it to the class.

For example:

public class ImageInfo
{
    public string Title { get; set; }
    public string Image { get; set; }
}

Then your method returns the class:

public ImageInfo GetImage(string name)
{                
    ImageInfo info = new ImageInfo();

    using (WebClient client = new WebClient())
    {
        var uri = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=pageimages&pithumbsize=400&titles="+name;
        string requestUrl = string.Format(uri, name);
        var response = client.DownloadString(new Uri(uri));
        var responseJson = JsonConvert.DeserializeObject<ImgRootobject>(response);
        var firstKey = responseJson.query.pages.First().Key;
        info.Image = responseJson.query.pages[firstKey].thumbnail.source;
        info.Title = responseJson.query.pages[firstKey].title;

        var hash = uri.GetHashCode();

    }
    return info;
}
Steve
  • 9,335
  • 10
  • 49
  • 81
3

You can only return 1 value from a function. So to tackle this you have 2 options:

  • Use the out parameter of a function
  • Return an custom object which has 2 properties

Custom object solution:

public class ImageResult
{
    string ImageUrl { get; set; }
    string Title { get; set; }
}

public ImageResult GetImage(string imageTitle)
{                
    ImageResult result = new ImageResult();

    using (WebClient client = new WebClient())
    {
        var uri = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=pageimages&pithumbsize=400&titles="+imageTitle;
        string requestUrl = string.Format(uri, imageTitle);
        var response = client.DownloadString(new Uri(uri));
        var responseJson = JsonConvert.DeserializeObject<ImgRootobject>(response);
        var firstKey = responseJson.query.pages.First().Key;

        result.ImageUrl = responseJson.query.pages[firstKey].thumbnail.source;
        result.Title = responseJson.query.pages[firstKey].title;

        var hash = uri.GetHashCode();

    }
    return result;
}

private void button1_Click(object sender, EventArgs e)
{
    pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;

    var imageResult = _imageService.GetImage(textBox1.Text);

    pictureBox1.LoadAsync(imageResult.ImageUrl);
    label1.Text = imageResult.Title;
}
Irshad
  • 3,071
  • 5
  • 30
  • 51
RvdK
  • 19,580
  • 4
  • 64
  • 107
2

You can't return multiple values from a method like that.

Change the method profile to:

private Tuple<string, string> GetImage(string name)

and the return statement to:

return new Tuple<string, string>(result1, result2);

Then you can pull each result out of the Tuple:

var resultTuple = _imageService.GetImage(textBox1.Text);
label1.Text = resultTuple.Item1;
label2.Text = resultTuple.Item2;
ChrisF
  • 134,786
  • 31
  • 255
  • 325
2

There are several options to choose from.

You can return Dictionary like this:

        public Dictionary<string, string> GetImage(string name)
        {
            string result1;
            string result2;

            using (WebClient client = new WebClient())
            {
                    var uri = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=pageimages&pithumbsize=400&titles="+name;
                    string requestUrl = string.Format(uri, name);
                    var response = client.DownloadString(new Uri(uri));
                    var responseJson = JsonConvert.DeserializeObject<ImgRootobject>(response);
                    var firstKey = responseJson.query.pages.First().Key;
                    result1 = responseJson.query.pages[firstKey].thumbnail.source;
                    result2 = responseJson.query.pages[firstKey].title;

                    var hash = uri.GetHashCode();

            }
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add("Source", result1);
            dictionary.Add("Title", result2);
            return dictionary;
        }

Then you can consume dictionary like this:

    private void button1_Click(object sender, EventArgs e)
    {
        pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
        Dictionary<string, string> imageDictionary = _imageService.GetImage(textBox1.Text);
        pictureBox1.LoadAsync(imageDictionary["Source"]);
        label1.Text = imageDictionary["Title"];
    }

You could also return List, or use out parameter, or as noted by other answers you can create a custom class and return it.

foobar
  • 695
  • 9
  • 17
  • ,Thank you for your answer.Bit while I write your code it is showing an error. in form1.cs it says The name 'GetImage' does not exist in the current context – Nowshin Jan 12 '16 at 11:26
  • Thanks @nick, I've updated the answer. It should be _imageService.GetImage – foobar Jan 12 '16 at 12:01
1

Since a method can have only one return value you can use out parameter to return an additional value.

public string GetImage(string name, out string title)
{
    string result1;

    using (WebClient client = new WebClient())
    {
        var uri = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=pageimages&pithumbsize=400&titles="+name;
        string requestUrl = string.Format(uri, name);
        var response = client.DownloadString(new Uri(uri));
        var responseJson = JsonConvert.DeserializeObject<ImgRootobject>(response);
        var firstKey = responseJson.query.pages.First().Key;
        result1 = responseJson.query.pages[firstKey].thumbnail.source;
        title = responseJson.query.pages[firstKey].title;

        var hash = uri.GetHashCode();
     }
     return result1;
 }

Usage;

private void button1_Click(object sender, EventArgs e)
{
     string title = string.Empty;

     pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
     pictureBox1.LoadAsync(_imageService.GetImage(textBox1.Text, out title));
     label1.Text = title;
}
Irshad
  • 3,071
  • 5
  • 30
  • 51
1

Using tuples. Example

using System;

class Program
{
    static void Main()
    {
    // Create three-item tuple.
    Tuple<int, string, bool> tuple =
        new Tuple<int, string, bool>(1, "cat", true);
    // Access tuple properties.
    if (tuple.Item1 == 1)
    {
        Console.WriteLine(tuple.Item1);
    }
    if (tuple.Item2 == "dog")
    {
        Console.WriteLine(tuple.Item2);
    }
    if (tuple.Item3)
    {
        Console.WriteLine(tuple.Item3);
    }
    }
}

font http://www.dotnetperls.com/tuple

Juliano Oliveira
  • 868
  • 1
  • 9
  • 29
  • Well tuples work but they hide what it in it. I would always suggest custom objects for reability. – RvdK Jan 12 '16 at 11:01
1

You can use a class:

public class Image
{
    public string Url { get; internal set; }
    public string Title { get; internal set; }

    public Image(string name)
    {
       string result1;
       string result2;

        using (WebClient client = new WebClient())
        {
            var uri = "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=pageimages&pithumbsize=400&titles="+name;
            string requestUrl = string.Format(uri, name);
            var response = client.DownloadString(new Uri(uri));
            var responseJson = JsonConvert.DeserializeObject<ImgRootobject>(response);
            var firstKey = responseJson.query.pages.First().Key;
            result1 = responseJson.query.pages[firstKey].thumbnail.source;
            result2 = responseJson.query.pages[firstKey].title;

            var hash = uri.GetHashCode();

        }
        Url = result1;
        Title = result2;
    }
}

And use it like this:

private void button1_Click(object sender, EventArgs e)
{
    var img = _imageService.GetImage(textBox1.Text);

    pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
    pictureBox1.LoadAsync(img.Url);
    label1.Text = img.Title;
}
nano
  • 455
  • 4
  • 16
0

Anonymously:

dynamic Get()
{
    return new {Url = "url", Image = "image"};
}

var result = Get();

var url = (string) result.Url;

Although, this is generally better suited to LINQ.

Meirion Hughes
  • 24,994
  • 12
  • 71
  • 122