J-K
J-K

Reputation: 139

Add image URL in CardImage of HeroCard

I am building a HeroCard containing a CardImage which must show an image. Up until now I was using

HeroCard hcBody = new HeroCard
{
    Text = "IMG",
    Images = new List<CardImage> { 
       new CardImage(url: $"https://www.example.com/Pictures/" + picNo + ".jpg") },
    Buttons = new List<CardAction> { 
       new CardAction(ActionTypes.ImBack, "SELECT"+picNo , value: picvalue) },
 };
 msg.Attachments.Add(hcBody.ToAttachment());

This is the HeroCard with a text,the image loaded from a URL adding the image number dynamically and at the end its type. Then I am adding a button with an action,text and value

Now the issue is that I need to load the images from the project's path. I tried to achieve it by

var picPath=System.Configuration.ConfigurationManager.AppSettings["picServerPath"];

and modifying the CardImage url to

Images = new List<CardImage> { new CardImage(url: picPath+ picNo + ".jpg") }

Using a logger I saw that the built path is correct, the HeroCard shows up but the images are missing. So I guess the URL of the CardImage needs to be created in a different way if I want to use the project's path on the server?

Upvotes: 1

Views: 889

Answers (1)

Andr&#233; Mantas
Andr&#233; Mantas

Reputation: 492

You need to make sure that every URL you use when creating a CardImage is a valid absolute HTTPS URL (otherwise it wont work in Facebook for example). Remember that these URLs will be rendered in the client device so they must be accessible from anywhere.

First, if you want to host the images in your bot webapp, make sure they are in the wwwroot folder.

Second, I'd recommend having a setting in appsettings.json with the base url where your images will be hosted (for example https://www.example.com/Pictures/).
For now it can be your bot webapp domain and later it can be a blob storage, or whatever.
Then make a simple class with a method that receives the image name and prefixes it with this setting so you don't need to repeat the same code in every dialog. Example:

appsettings.json

{
  "ImagesBaseUrl": "https://www.example.com/Pictures/",
  "..."
}

Service

public interface IImageService
{
    string GetImagePath(string imageName);
}

public class ImageService : IImageService
{
    private readonly string _baseUrl;

    public ImageService(IConfiguration configuration)
    {
        _baseUrl = configuration?.GetValue<string>("ImagesBaseUrl") ?? throw new ArgumentNullException(nameof(configuration));
    }

    // probably improve this further with / checking, handle extensions, etc
    public string GetImagePath(string imageName)
    {
        return string.Concat(_baseUrl, imageName);
    }
}

Then inject IImageService in your bot/dialog or wherever you need to build hero cards.

Edit: If you really want to get the server absolute path your app is running on, you'll have to use something like Server.MapPath

However if you're using BotFramework V4 you're probably using NET Core so you'll have to use one of these depending on your NET Core version. You'd better injecting IHostingEnvironment/IWebHostEnvironment in a single place like the service I mentioned above. Just imagine they change it again in the future and you'd have to rename in lots of dialogs.

I'd still prefer to use the appsettings version since its more versatile in case you want to change it in the future (you don't have to change code and rebuild the app).

Upvotes: 1

Related Questions