0
votes

I am using MVC, Entity Framework, Durandal and Breeze JS. I've got a user which looks like such (simplified):

public class User : EntityBase<Guid>, IAggregateRoot
{
    public Guid Id { get; set; }
    public string UserName { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [ForeignKey("UserImage")]
    public virtual Guid? ImageId { get; set; }

    public virtual UserImage UserImage { get; set; }
}

The UserImage class looks like such. I know I should limit the size of the Image. (Maybe this is the issue?):

public class UserImage
{
    public Guid Id { get; set; }

    [MaxLength]
    public byte[] Image { get; set; }        
}

I've got an api function on the server to get the current user:

public IQueryable<User> GetCurrentUser()
    {
        IPrincipal principal = HttpContext.Current.User;
        var users = _uow.Users.FindBy(u => u.UserName.Equals(principal.Identity.Name));
        if (!users.Any())
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Unauthorized));
        }

        return users;
    }

And two calls on the client which get the current user. The first is in the shell:

function loadCurrentUser() {
        return uow.CurrentUser.all().then(function (newUser) {
            log('Welcome to the Site ' + newUser[0].FullName() + '!', newUser[0], true);
            config.CurrentUser(newUser[0]);
            return true;
        });
    }

The second is in a ManageUser viewmodel:

function activate() {
                    return uow.CurrentUser.all(['UserImage']).then(function (user) {
                        self.CurrentUser(user[0]);
                        return $.when(init()).then(boot());
                    }).fail(function() {
                        return router.activate('accounts/login');
                    });
                }

Now I can load an Image into the ManageUser page and save and in fiddler it shows that the ImageId and Image are being sent across to the server. Then I checked the BeforeSaveEntity intercept and shows two entities being saved.

  1. Updated User with ImageId set
  2. New UserImage

The data is also visible in the database. Now when I refresh the Manage User page I can see the two GetCurrentUser calls in fiddler.

  1. From the shell call I can see that the User is being returned and an ImageId is set but no UserImage was sent over because didn't expand the query.
  2. From the Manage User call I see the User is returned but only the ImageId is sent over and the Image object was OMITTED from the JSON.

Has anyone come across this issue with images? All my other expands appear to be working correctly. Does anyone have any examples on using breeze to save just the filepath to the image and possibly using windows azure for media storage?

1

1 Answers

0
votes

I know this probably won't answer your question but I would propose not sending the byte array to the client and rather have an Image Handler on the server side that takes an ImageId as a parameter and then return the image with the relevant Content Type set. An example of this can be found here.

By using this approach you could reference your image from HTML using an img tag with the source set to the Image Hander with the relevant ImageId.

An example using knockout for data binding would be:

<a data-bind="attr: {href: '/Image/' + User.ImageId()}"></a>

This approach enables you to easily add caching on both the server and client which will improve performance. It also removed the need to convert the byte array to an image on the client side, which may or may not be a pain.

Edit:

When saving the managed user, post the Image to an Upload action on the ImageHandler (have a look at this article). This action must return the new Id of the image. After you've received the new Id, update the User.ImageId on client side and call SaveChanges on breeze.