So I must be doing something wrong here, just not sure what it is yet. My original PoC worked fine, but wasn’t MVVM, so I have lost something in the translation.
So I browse to a file to choose for an upload, everything starts working fine. It transfers the first chunk up to the server and then my complete event is never called. And that will be sending all of the additional chunks in the array, so the file is incomplete.
Am I just missing a step?
And if it matters, the service is setup on IIS7, but I’m not sure if anything needs to be setup on the service side to make this happen. It just ‘worked’ in the PoC code when I was using the XAML code-behind.
Model Code:
public void uploadChunks(int index, string fileName)
{
FileUpload fileUpload = new FileUpload();
FileUpload.FileName = fileName;
FileUpload.chunk = fileChunks[index];
context.UploadFileAsync(fileUpload);
}
FileUploadServiceSoapClient context = new FileUploadServiceSoapClient("BasicHttpBinding_FileUploadServiceSoap");
int chunkSize = 15306;
public List<byte[]> fileChunks;
public double TotalChunks { get; set; }
/// <summary>
/// Convert file to an array of file chunks to stream to the upload location
/// </summary>
/// <param name="imageFile"></param>
public void convertToChunks(byte[] imageFile)
{
TotalChunks = Math.Ceiling((double)imageFile.Length / (double)chunkSize);
fileChunks = new List<byte[]>();
for (int i = 0; i < TotalChunks; i++)
{
byte[] chunk;
int startIndex = i * chunkSize;
if (startIndex + chunkSize > imageFile.Length)
chunk = new byte[imageFile.Length - startIndex];
else
chunk = new byte[chunkSize];
Array.Copy(imageFile, startIndex, chunk, 0, chunk.Length);
fileChunks.Add(chunk);
}
}
ViewModel Code
public UploadViewModel()
{
uploadModel = new UploadModel(); // important – must initialize model
OpenFileCommand = new RelayCommand(OpenDialog);
StatusText = "Please select a file to upload";
context.UploadFileCompleted += new EventHandler<AsyncCompletedEventArgs>(context_UploadFileCompleted);
}
private void OpenDialog()
{
OpenFileDialog ofd = new OpenFileDialog();
if ((bool)ofd.ShowDialog())
{
_fileName = ofd.File.Name;
FileStream fs = ofd.File.OpenRead();
fileSize = (double)fs.Length;
index = 0;
sendData = 0;
byte[] file = new byte[fs.Length];
fs.Read(file, 0, file.Length);
// call our model and convert file into chunks
uploadModel.convertToChunks(file);
// start upload process, this only sends the first chunk all subsquent chunks
// are sent on the context_UploadFileToCrmCompleted function
uploadModel.uploadChunks(index, _fileName);
}
}
void context_UploadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error == null)
{
sendData += uploadModel.fileChunks[index].Length;
TotalFileSize = byteTranslation(sendData) + "/" + byteTranslation(fileSize);
if ((index + 1) < uploadModel.fileChunks.Count)
{
this.CurrentProgress = index / uploadModel.fileChunks.Count;
index += 1;
uploadModel.uploadChunks(index, _fileName);
}
else
{
StatusText = "Successfully uploaded. Submitting to the file repository...";
// Submit the upload to SharePoint
}
}
}
I hope I am not missing anything… do you have two FileUploadServiceSoapClients?
One in the ViewModel and one in the model. You are calling the service in the model but the completed handler is assigned to the context of the ViewModel.
So you have to write
instead of
Probably you should better not use the ServiceClient directly in the viewModel but pass a callback or let the model raise an own event.