Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing json in a hidden field to deserialize to a model property list

Good morning all. I've been pondering over the best way to use plupload with my mvc web app to marry up uploaded files with their respective record when created on the back-end.

I've finally boiled it down to the following process - this will work for both new and existing records (think CMS):

  1. Create new record, use plupload to upload multiple files.
  2. Multiple files (series of json strings representing each file) are stored on the client then posted back via hidden field.
  3. A property on the model for the form holds the result of these uploaded files so I can handle the back-end business.

The model (without the fluff of unrelated properties) will look like this:

public class Record{
    public IList<ClientFile> Files {get;set;}
}

Client file looks like this:

public class ClientFile{
    public string UniqueId{get;set;}
}

My problem lies with what I have on the client after each successful upload (a json string of ClientFile) and how I can correctly get this into hidden field and bound correctly so I can have the list of client files ready in my model.

I'm thinking along the lines of either structuring the hidden field(s) right so the binder knows how to wire them up to the list, or having do some some custom deserializing myself to turn the collection of json strings into a list of objects.

Does anyone have any wisdom before I lose my bank holiday weekend to mvc.

like image 241
Phil Cooper Avatar asked Jun 03 '12 09:06

Phil Cooper


2 Answers

This is how I achieve it now:

public class ProductModel
{
    // This is the field bound to the view (hidden field)
    public string FilesValue
    {
        get
        {
            return Files.ToJson<IEnumerable<Plupload>>();
        }
        set
        {
            Files = value.FromJson<IEnumerable<Plupload>>();
        }
    }
    public IEnumerable<Plupload> Files { get; private set; }
}

(ToJson & FromJson are just an extension methods I use to serialise and deserialise objects quickly.)

In my view:

<input type="hidden" name="FilesValue" id="FilesValue" />

I have an inline script that converts the value of the hidden field when the form is loaded:

Bundles.AddInlineScript("fileManager.dserialize('" + Html.Raw(Model.FilesValue) + "')");

And the client script which runs before the form is posted to the server:

function preSubmit(e) {
// need to force upload
var $form = $(e.currentTarget),
    hidden = $form.find('#FilesValue')[0];
if (uploader.files.length > 0) {
  uploader.bind('UploadComplete', function () {
    serialize(hidden);
    $form.trigger('submit');
  });
  uploader.start();
  return false;
} else {
  serialize(hidden);
  return true;
}
}

n.b uploader is a reference to plupload and serialize() is a local method which turns the file array into json which gets posted back.

like image 122
Phil Cooper Avatar answered Oct 13 '22 15:10

Phil Cooper


Your client html before post should be like this:

<input type="hidden" name="Files[0].UniqueId" value"XX" />
<input type="hidden" name="Files[1].UniqueId" value"XX" />
<input type="hidden" name="Files[2].UniqueId" value"XX" />

Assuming you have a callback function for each file uploaded with a parameter containg the JSON string you can create dinamically the hiddens with jQuery after uploading each file like this:

....
var i = 0;
....
function(data){
     $('form').append('<input type="hidden" name="Files[' +i+'].UniqueId" value"' 
                       + data.UniqueId + '" />');
     i++;
}
like image 42
mcorte Avatar answered Oct 13 '22 17:10

mcorte