Unexpected end of stream at Microsoft.AspNetCore.WebUtilities.MultipartReaderStream - asp.net-core

System.IO.IOException: Unexpected end of stream.
at Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.<ReadAsync>d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions.<DrainAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.WebUtilities.MultipartReader.<ReadNextSectionAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at AspNetCoreFileUpload.Controllers.FileUploadController.<Index>d__0.MoveNext()
in C:\\GitHub\\StackOverflow\\LargeFileUploadController\\FileUploadController.cs:line 29
Repro: https://github.com/bigfont/StackOverflow/tree/master/LargeFileUploadController
Form
<form action = ""/FileUpload"" method=""post"" enctype=""multipart/form-data"">
<label for=""myfile1"">File</label>
<input type=""file"" name=""myFile1"" />
<label for=""myfile2"">File</label>
<input type=""file"" name=""myFile2"" />
<input type=""submit"" value=""Send"" />
</form>
Controller
public class FileUploadController : Controller
{
[HttpPost]
public async Task<IActionResult> Index()
{
var boundary = GetBoundary(Request.ContentType);
var reader = new MultipartReader(boundary, Request.Body);
try
{
var section = await reader.ReadNextSectionAsync();
}
catch (System.Exception ex)
{
return new OkObjectResult(new { ex = ex.ToString() });
}
return new OkObjectResult(new { message = "Done" });
}
private static string GetBoundary(string contentType)
{
var elements = contentType.Split(' ');
var element = elements.Where(entry => entry.StartsWith("boundary=")).First();
var boundary = element.Substring("boundary=".Length);
// Remove quotes
if (boundary.Length >= 2 &&
boundary[0] == '"' && boundary[boundary.Length - 1] == '"')
{
boundary = boundary.Substring(1, boundary.Length - 2);
}
return boundary;
}
}

I got almost the same exception recently. I'm saying almost because they actually renamed the exception to Unexpected end of Stream, the content may have already been read by another component., which actually means that something already consumed the body stream. The comments of the following change gives us the understanding of what's happening:
Tratcher commented on Mar 23
...The MVC model binder reads the form and buffers the multipart segments
for you, so there's no point in re-parsing request body with the
MultipartReader...
So, the question is how to disable the default form binding (reading the request form)?
I found the DisableFormValueModelBindingAttribute attribute in this Mvc.FileUpload sample which disables the form binding and this is what it looks like:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var formValueProviderFactory = context.ValueProviderFactories
.OfType<FormValueProviderFactory>()
.FirstOrDefault();
if (formValueProviderFactory != null)
{
context.ValueProviderFactories.Remove(formValueProviderFactory);
}
var jqueryFormValueProviderFactory = context.ValueProviderFactories
.OfType<JQueryFormValueProviderFactory>()
.FirstOrDefault();
if (jqueryFormValueProviderFactory != null)
{
context.ValueProviderFactories.Remove(jqueryFormValueProviderFactory);
}
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
If you want some more information, you can check out the following:
Create a filter/sample that shows how to remove the form value providers (rynowak opened this issue on Apr 26)
Sample: Issues with Antiforgery + Form + File Uploads (rynowak opened this issue on Apr 26)
Just for info - as commented before, the MVC model binder reads the form, but where can one find the results. The results can be found in the HttpRequest.Form, which has Files.

Don't know if this might help you but I came across simular issue "Unexpected end of Stream, the content may have already been read by another component".
app.Use(async (context, next) => {
context.Request.EnableRewind();
await next();
});
Code above were added in Startup.cs Configure method.
Hope it helps

I created a MemoryStream, copied stream from body there and it was working like a charm :) Point is you cannot read Stream twice. However, this is not a case for MemoryStream. Of course, you have to be sure about scaling, I don't think this will work for really big files uploaded. I didn't tested this.
I rewrote example from Microsoft site: enter link description here
Here is part of it:
while (section != null)
{
ContentDispositionHeaderValue contentDisposition;
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
if (hasContentDispositionHeader)
{
if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
{
var ms = new MemoryStream();
var fileSection = section.AsFileSection();
await fileSection.FileStream.CopyToAsync(ms);
ms.Position = 0;
documentUpload.Attachments.Add(new SimpleFileInstance { FileName = fileSection.FileName, FileStream = ms });
}
else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
{
// Content-Disposition: form-data; name="key"//
// value
// Do not limit the key name length here because the
// multipart headers length limit is already in effect.
var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name).Value;
var encoding = GetEncoding(section);
using (var streamReader = new StreamReader(
section.Body,
encoding,
detectEncodingFromByteOrderMarks: true,
bufferSize: 1024,
leaveOpen: true))
{
// The value length limit is enforced by MultipartBodyLengthLimit
var value = await streamReader.ReadToEndAsync();
if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
{
value = string.Empty;
}
formAccumulator.Append(key, value);
if (formAccumulator.ValueCount > DefaultFormOptions.ValueCountLimit)
{
throw new InvalidDataException($"Form key count limit {DefaultFormOptions.ValueCountLimit} exceeded.");
}
}
}
}
section = await reader.ReadNextSectionAsync();
}
documentUpload is our DTO to work further with files. In our case, some documents gets uploaded to SharePoint.

Related

Unit testing using Fakes gives IConvertible exception

What I have
The interface:
public interface IDocDbRepository
{
Task<JObject> UpdateDocumentAsync(JObject updatedDocument);
}
The implementation:
public async Task<JObject> UpdateDocumentAsync(JObject updatedDocument)
{
if (updatedDocument == null)
{
throw new ArgumentNullException(nameof(updatedDocument));
}
var response = await this.documentDBClient.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(this.dbName, this.collectionName, updatedDocument["id"].Value<string>()), updatedDocument).ConfigureAwait(false);
return JObject.Parse(response.Resource.ToString());
}
The exception occurs in the await line.
The Unit Test:
static Guid docGuid = Guid.NewGuid();
[TestMethod]
public async Task TestMethod2()
{
var jObject = new JObject { { "id", docGuid }, { "studentId", "1" }, { "courseId", "Ph" } };
// Arrange
var docClient = new ShimDocumentClient();
ShimDocumentClient.AllInstances.CreateDocumentAsyncUriObjectRequestOptionsBoolean =
(instance, uri, document, options, disableAutomaticGeneration) => Task.FromResult(new ResourceResponse<Document>(new Document() { Id = docGuid.ToString() }));
// Act
var documentRepository = new DocDbRepository(endPointUri, accountKey, dbName, collectionName);
try{
var response = await documentRepository.UpdateDocumentAsync(jObject).ConfigureAwait(false);
}
catch(Exception ex){}
// Assert
Assert.AreEqual(response.Count, 1);
}
The test does not go beyond the UpdateDocumentAsync part and exits with this message:
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at Newtonsoft.Json.Linq.Extensions.Convert[T,U](T token)
at Newtonsoft.Json.Linq.Extensions.Value[T,U](IEnumerable`1 value)
at Newtonsoft.Json.Linq.Extensions.Value[U](IEnumerable`1 value)
at Common.DataAccess.DocumentDb.DocDbRepository.<UpdateDocumentAsync>d__12.MoveNext() in C:\Common\Common.DataAccess.DocumentDb\DocDbRepository.cs:line 196
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Common.DataAccess.DocumentDb.Tests.DocDbUtilityTests.<TestMethod2>d__9.MoveNext() in C:\Common\Common.DataAccess.DocumentDb.Tests\DocDbUtilityTests.cs:line 113
This is my first time with Fakes framework.
Any help is greatly appreciated.
Thanks in advance.
Regards.
This appears to be a problem with your serialization code. Specifically, this statement:
updatedDocument["id"].Value<string>()
The Value extension method appears to require that the source implement the IConvertible interface, which is not implemented by Guid.

How to create a SecondaryTile on Windows Phone 8.1?

I'm trying to create a Tile on the Windows Phone start screen. The following code used to work but now it doesn't. I didn't change anything.
private async static void CreateTile()
{
try
{
SecondaryTile tileData = new SecondaryTile()
{
TileId = "MyTileID",
DisplayName = "My App Name",
TileOptions = TileOptions.ShowNameOnLogo,
};
tileData.VisualElements.Square150x150Logo = new Uri("ms-appx:///Resources/Images/Tiles/150150.png", UriKind.Absolute);
tileData.VisualElements.ShowNameOnSquare150x150Logo = true;
await tileData.RequestCreateAsync();
}
catch (Exception ex)
{
}
}
Now it's failing with the error message:
The parameter is incorrect.
and the following Stack Trace:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at My.Namespace.SplashPage.<CreateTile>d__f.MoveNext()
I even get the error when I comment everything out, for example:
SecondaryTile tileData = new SecondaryTile()
{
//TileId = "MyTileID",
//DisplayName = "My App Name",
//TileOptions = TileOptions.ShowNameOnLogo,
};
//tileData.VisualElements.Square150x150Logo = new Uri("ms-appx:///Resources/Images/Tiles/150150.png", UriKind.Absolute);
//tileData.VisualElements.ShowNameOnSquare150x150Logo = true;
await tileData.RequestCreateAsync();
So I don't know what parameter is incorrect. What could be causing this? How can I fix it?
Try something like this:
if (SecondaryTile.Exists(tileID)) await tileData.UpdateAsync();
else await tileData.RequestCreateAsync();

Read file local storage windowsphone

I try to read xml files from my windows application.
In this one, I add a folder in Assets/Mocks/clubic.xml (build action : content) to use the data in the xml file as a mock.
So I try to use the following code
var package = Windows.ApplicationModel.Package.Current;
var installedLocation = package.InstalledLocation;
try
{
StorageFile sampleFile = await installedLocation.GetFileAsync("Assets/Mocks/clubic.xml");
}
catch (Exception ex)
{
throw ex;
}
try
{
StorageFile sampleFile = await installedLocation.GetFileAsync("ms-appx:///Assets/Mocks/clubic.xml");
}
catch (Exception ex)
{
throw ex;
}
I obtain for the two cases, the same exception
System.ArgumentException: Value does not fall within the expected range.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at FileReadWrite.MainPage.d__17.MoveNext()}
I try to use this code
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
if (local != null)
{
// Get the DataFolder folder.
var dataFolder = await local.GetFolderAsync("Assets/Mocks");
// Get the file.
var file = await dataFolder.OpenStreamForReadAsync("clubic.xml");
// Read the data.
using (StreamReader streamReader = new StreamReader(file))
{
this.textBlock1.Text = streamReader.ReadToEnd();
}
}
I still obtain the same issue.
Can you help me.
best regards,
Alexandre
Try this
StorageFile sampleFile = await installedLocation.GetFileAsync(#"Assets\Mocks\clubic.xml");
Here's what I've done in an app of mine to read a file that's built as Content:
var resource = System.Windows.Application.GetResourceStream(new Uri(#"Assets\Mocks\clubic.xml", UriKind.Relative));
using (StreamReader sr = new StreamReader(resource.Stream)) {
this.textBlock1.Text = await sr.ReadToEndAsync();
}

How do I log EntityValidation errors using ELMAH MVC?

I've been writing an application using MVC4 and EF5.x, and using ELMAH for logging exceptions for review. We recently released the application, and as expected the ELMAH log filled up with several dozen exceptions. Great (and not)! The problem is that one of those exceptions is
System.Data.Entity.Validation.DbEntityValidationException
Validation failed for one or more entities.
See 'EntityValidationErrors' property for more details.
Of course, there's no way to see the EntityValidationErrors property for more details and the stack trace wraps up to my SubmitChanges()
I know ELMAH has the capability of allowing us to raise our own exceptions, and in some way customize what gets logged and how. Unfortunately, I'm still very new to ELMAH and MVC and a Google search didn't turn up anything relevant. I did find a blog article on logging EntityValidationErrors, and the author specifically mentioned that he would post how to do so in ELMAH but that was posted in September of 2012 and I didn't see anything since then.
Any help would be greatly appreciated!
Probably the best thing to do in this case would be to wrap your context.SaveChanges(); call in a try...catch block and then log the individual items from the ValidationExceptions. Something like the following should get you started:
try
{
context.SaveChanges();
}
catch (DbEntityValidationException ve)
{
var error = ve.EntityValidationErrors.First().ValidationErrors.First();
var msg = String.Format("Validation Error :: {0} - {1}",
error.PropertyName, error.ErrorMessage);
var elmahException = new Exception(msg);
Elmah.ErrorSignal.FromCurrentContext().Raise(elmahException);
}
How about this extension method based on the above..
public static void SaveChangesWithBetterValidityException(this DbContext context)
{
try
{
context.SaveChanges();
}
catch (DbEntityValidationException ve)
{
var errors = new List<string>();
foreach (var e in ve.EntityValidationErrors)
{
errors.AddRange(e.ValidationErrors.Select(e2 => string.Join("Validation Error :: ", e2.PropertyName, " : ", e2.ErrorMessage)));
}
var error = string.Join("\r\n", errors);
var betterException = new Exception(error, ve);
throw betterException;
}
}
Elmah will then have a much better exception in it's log
I added the following to my Global.asax.cs in order to forward all DbEntityValidationException exceptions to Elmah across my MVC application:
private void ElmahEntityValidationException()
{
var dbEntityValidationException = Server.GetLastError() as DbEntityValidationException;
if (dbEntityValidationException != null)
{
var errors = new List<string>();
foreach (var entityError in dbEntityValidationException.EntityValidationErrors)
{
errors.AddRange(entityError.ValidationErrors.Select(e2 => string.Join("Validation Error :: ", e2.PropertyName, " : ", e2.ErrorMessage)));
}
var error = string.Join("\r\n", errors);
var betterException = new Exception(error, dbEntityValidationException);
Elmah.ErrorSignal.FromCurrentContext().Raise(betterException);
}
}
protected void Application_Error(object sender, EventArgs e)
{
ElmahEntityValidationException();
}
Some of this code was reused from #Paige Cook's and #Original10's posts.
Re-throwing as per the code below is not perfect (although I don't mind resetting the call stack here, as Elmah's logged details of the address posted to will show me what lead to the exception) and you will have to work out your own security implications, but this is fairly concise & meets my needs:
try
{
return base.SaveChanges();
}
catch (DbEntityValidationException e)
{
var de = new DetailedEntityValidationException(e);
throw de;
}
public class DetailedEntityValidationException : Exception
{
public DetailedEntityValidationException(DbEntityValidationException ve)
: base(ve.Message + ":\r\n\t-" + string.Join(new string('-',20) + "\r\n\t-", ve.EntityValidationErrors.Select(ev=>string.Join("\r\n\t-",ev.ValidationErrors.Select(e=>e.ErrorMessage)))))
{}
}
Here is my implementation for Global Web API solution for Elmah and EF Validation errors:
public class ElmahHandleWebApiErrorAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
var e = context.Exception;
// Try parse as entity error (i'm not sure of performance implications here)
var efValidationError = e as DbEntityValidationException;
if (efValidationError == null)
{
RaiseErrorSignal(e);
}
else
{
RaiseEntityFrameWorkValidationErrorSignal(efValidationError);
}
}
private static bool RaiseErrorSignal(Exception e)
{
var context = HttpContext.Current;
if (context == null)
return false;
var signal = ErrorSignal.FromContext(context);
if (signal == null)
return false;
signal.Raise(e, context);
return true;
}
private static bool RaiseEntityFrameWorkValidationErrorSignal(DbEntityValidationException e)
{
var context = HttpContext.Current;
if (context == null)
return false;
var signal = ErrorSignal.FromContext(context);
if (signal == null)
return false;
//Taken from post above
var errors = new List<string>();
foreach (var entityError in e.EntityValidationErrors)
{
errors.AddRange(entityError.ValidationErrors.Select(e2 => string.Join("Validation Error :: ", e2.PropertyName, " : ", e2.ErrorMessage)));
}
var error = string.Join("\r\n", errors);
var betterException = new Exception(error, e);
signal.Raise(betterException, context);
return true;
}
}
and then I register the attribute in the WebApiConfig.cs file under App_Start
config.Filters.Add(new ElmahHandleWebApiErrorAttribute());

The request was aborted: Could not create SSL/TLS secure channel in Windows 8 Metro App

I have a list of 350 downloadable image urls. I download 10 images parallely at one shot by running multiple tasks. But after downloading N number of images suddenly my code throws the following exception.
Exception: "An error occurred while sending the request."
InnerException: "The request was aborted: Could not create SSL/TLS
secure channel."
StackTrace: "at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task)\r\n at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task)\r\n at
System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n ...
I have created a sample project to reproduce this exception. I have 2 test-cases in my hand. You can download the running test project from My Sky Drive Here. Right click on the file HTTPClientTestCases1and2.zip and download.
Case 1: Using a single instance HttpClient for all image Download.
In this case I'm sending parallel request to 10 urls using same HttpClient. In this case download is successful for most of the time. After last successful download of an image wait for minimum 40 seconds (Max 1 minute 40 seconds) to send the next parallel download request for the next batch. One image will definitely fail due to this exception. But so many places its written and suggested to use single HttpClient for multiple request.
public async void DownloadUsingSingleSharedHttpClient(Int32 imageIndex)
{
Uri url = new Uri(ImageURLs[imageIndex]);
UnderDownloadCount++;
try
{
Byte[] contentBytes = null;
try
{
// Exception IS THROWN AT LINE BELOW
HttpResponseMessage response = await _httpClient.GetAsync(url);
contentBytes = await response.Content.ReadAsByteArrayAsync();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Download Failed at GetAsync() :" + ex.Message);
throw ex;
}
DownloadedCount++;
if (OnSuccess != null)
OnSuccess(this, new DownloadSuccessEventArgs() { Index = imageIndex, Data = contentBytes });
}
catch (HttpRequestException hre)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(hre, null);
}
catch (TaskCanceledException hre)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(hre, null);
}
catch (Exception e)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(e, null);
}
}
Case 2: Creating new instance of HttpClient for every image Download
In this case it just fails very frequently due to same exception while downloading images parallely.
public async void DownloadUsingCreatingHttpClientEveryTime(Int32 imageIndex)
{
Uri url = new Uri(ImageURLs[imageIndex]);
UnderDownloadCount++;
try
{
Byte[] contentBytes = null;
using (HttpClientHandler _handler = new HttpClientHandler())
{
_handler.AllowAutoRedirect = true;
_handler.MaxAutomaticRedirections = 4;
using (HttpClient httpClient = new HttpClient(_handler))
{
httpClient.DefaultRequestHeaders.ExpectContinue = false;
httpClient.DefaultRequestHeaders.Add("Keep-Alive", "false");
try
{
// Exception IS THROWN AT LINE BELOW
contentBytes = await httpClient.GetByteArrayAsync(url.OriginalString);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Download Failed :" + ex.Message);
throw ex;
}
}
_handler.Dispose();
}
DownloadedCount++;
if (OnSuccess != null)
OnSuccess(this, new DownloadSuccessEventArgs() { Index = imageIndex, Data = contentBytes });
}
catch (HttpRequestException hre)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(hre, null);
}
catch (TaskCanceledException hre)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(hre, null);
}
catch (Exception e)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(e, null);
}
}
Please edit the following function in MainPage.xaml.cs to check two cases
private void Send10DownloadRequestParallel()
{
for (Int32 index = 0; index < 10; index++)
{
Task.Run(() =>
{
Int32 index1 = rand.Next(0, myImageDownloader.ImageURLs.Count - 1);
UpdateDownloadProgress();
// Case 1: Download Using Single Shared HttpClient
// myImageDownloader.DownloadUsingSingleSharedHttpClient(index1);
// OR
// Case 2: Download Using Creating Http Client Every Time
myImageDownloader.DownloadUsingCreatingHttpClientEveryTime(index1);
});
}
}
My Question: What I'm doing wrong? What is the best way of implementing parallel downloader in WinRT by overcoming this exception.
I ran your sample application and am only get errors in a couple of scenarios:
When the image that your app is requesting does not exist, the .NET HTTP client throws an exception. Your handler doesn't quite handle this case, as the inner exception is NULL. I had to tweak that code just a little:
async void myImageDownloader_OnFailed(object sender, EventArgs e)
{
await App.CurrentDispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, delegate
{
TimeSpan time =(DateTime.Now -dateTimeSuccess);
String timeGap = "Ideal For:" + time.ToString() + "\n";
ErrorListBox.Text += "\n Failed When: " + DownloadInfo.Text + "\n";
ErrorListBox.Text += timeGap;
// CX - added null check for InnerException, as these are NULL on HTTP result status 404
var ex = sender as Exception;
if (ex.InnerException != null)
ErrorListBox.Text += ex.InnerException.Message;
else
ErrorListBox.Text += "Inner Exception null - Outer = (" + ex.ToString() + ")";
});
}
The only time I got your other error Could not create SSL/TLS secure channel in Windows 8 Metro App, is when I was using a HTTP debugging proxy (Fiddler). If I don't user Fiddler, which intercepts all HTTP(S) calls, then I have no problems downloading. I even started multiple downloads in rapid succession (by clicking the blue download area multiple times within one second). The result was that all items were downloaded (except for the 404 errors, as mentioned above).
Here is a screenshot of the successful downloads (again except for the 404s). This screenshot is running test case #2 (multiple instances of HttpClient). I did run test case #1 (single instance of HttpClient) and the results were also successful.
In short, I did not see the problems that you are experiencing. The only thing I can think of is for you to try your app from a different machine or location.