0

How can I get both the image and tooltip in a single call to a MVC controller method? I can use something like the following to get the image, but how to also get the associated tooltip? The use case is to display an image if the user is allowed to see the image, else display a generic image and a tooltip indicating why the image is not being shown.

To clarify, I would like to avoid two calls to the controller, once to get the image path and tooltip, and another to get the image file. Not only will this result in two round trips across the network, it would also repeat the validation checks. The problem is that the img src call only accommodates the image, not other properties such as the title associated with the image.

<img src="@Url.Action("GetPicture", "User", new { userId = Model.User.Id })" />
Manish
  • 1,726
  • 3
  • 23
  • 29

4 Answers4

0

Can't you just have a second method for GetTitle using the same permission logic from GetImage and return the appropriate text for each user? Then call this method for the title attribute.

Jodee Dex Page
  • 551
  • 5
  • 3
  • I could, but that results in two network round trips, and two executions of the same permission logic – Manish Jan 30 '16 at 16:03
0

Can you approach the problem in the following way.

Create Model

public class ImageViewModel
{
    public string ImagePath
    {
        get;
        set;
    }
    public string ImageTitle
    {
        get;
        set;
    }
}

Create a partial View

@using StackOverFlowProject.Models
@model ImageViewModel

<img src=@Model.ImagePath title=@Model.ImageTitle />

Your Controller

    public PartialViewResult _Image(string userID)
    {
        ImageViewModel model = new ImageViewModel();
        //Here You can check what image and tooltip you want show to the user
        //model = //FillData from DB / 
        return PartialView("_Image", model);
    }

and at last in Your MainView where you want to display the Image render the partial view

shu
  • 1,938
  • 10
  • 19
0

Not sure if this is the best way to do it, but I did it by creating an Ajax form, submitting it using jQuery, returning a JSON object with the byte array encoded as a Base64 string, and using Javascript to display the image. Seems to be working so far, will know more from further tests.

In the view:

<div id="imgDiv">
@using (Ajax.BeginForm("GetImg", "User", null, new AjaxOptions()
{
  HttpMethod = "POST",
  Url = Url.Action("GetImg", "User"),
  OnSuccess = "DisplayImageWithTooltip(data, 'imgDiv')",
}, new { id = "ImgForm", @class = "imageGetterWithTooltip" }))
{
  @Html.AntiForgeryToken()
  @Html.Hidden("userId", @Model.User.Id)
}
</div>

Javascript to submit form:

$(".imageGetterWithTooltip").submit();

In Controller (based on https://stackoverflow.com/a/9464137/1385857)

return Json(new
{
  fileBytes = Convert.ToBase64String(<File byte[]>), 
  fileType = <FileType>,
  tooltip = <toolTip>
}, JsonRequestBehavior.AllowGet);

Javascript to display image

function DisplayImageWithTooltip(data, target) {

  var oImg = document.createElement("img");
  oImg.width = 150;
  oImg.height = 150;
  oImg.setAttribute('src', "data:" + data.fileType + ";base64," + data.fileBytes);
  oImg.setAttribute('title', data.tooltip);

  document.getElementById(target).appendChild(oImg);
}
Community
  • 1
  • 1
Manish
  • 1,726
  • 3
  • 23
  • 29
0

Using Manish's ideas, my simplified solution is to create a partial view and supply it the image data directly:

Controller:

            vmMiniData data = new Models.vmMiniData();
            byte[] byteArray = Users.GetPersonnelImage(personnelID);
            if (byteArray != null)
            {
                data.ImageStr  = Convert.ToBase64String(byteArray);
            }
            else
            {
                data.ImageStr = Convert.ToBase64String(Users.GetPersonnelImage("00000000-0000-0000-0000-000000000000")); //get blank image                
            }
            data.CaptionStr = Users.GetUserJobTitle(personnelID);
            return PartialView("Personnel/MiniPersonnelPartial", data);

Model:

public static byte[] GetPersonnelImage(string personnelID)
{
    byte[] img = (byte[])(from record in db.PersonnelImages
                   .Where(R => R.PersonnelID == new Guid(personnelID))
                          select record.Image).FirstOrDefault();
    return img;
}

Then in the partial:

@model vmMiniData

<div>
    <div>@Model.CaptionStr</div>
    <div> <img src="data:image;base64,@Model.ImageStr" style="width:60px;min-height:30px;" /></div>
</div>

It works very well in MVC 5 :).

davaus
  • 1,145
  • 13
  • 16