我的观点: -
<form class="commentform commentright" enctype="multipart/form-data" >
<textarea class="simpleta required" name="Body" placeholder="Discuss this vehicle with other members of Row52."></textarea>
<input type="file" id="fileuploadfield" name="fileuploadfield"/>
<input type="submit" value="Submit" class="btn btn-inverse btn-small"/>
<input type="hidden" name="ParentId" value="0"/>
<input type="hidden" name="VehicleId" value="@Model.VehicleId"/>
<span class="commentcount"><span class="numberofcomments">@Model.Count</span>@count</span>
<div class="feedback"></div>
<img id="img" src="" />
</form>
JQuery: -
submitComment: function (form, type) {
var self = this;
var $this = $(form);
var formData = $this.serialize();
var $message = $this.find('.feedback');
$message.hide();
$message.html('');
var val = validation({ $form: $this });
if (val.checkRequired()) {
$this.indicator({ autoStart: false, minDuration: 100 });
$this.indicator('start');
var files = $("#fileuploadfield").get(0).files;
if (files.length > 0) {
if (window.FormData !== undefined) {
var data = new FormData();
for (var i = 0; i < files.length; i++) {
data.append("file" + i, files[i]);
}
}
else {
alert("This browser doesn't support HTML5 multiple file uploads!");
}
}
else {
alert("This");
}
$.ajax('/api/v2/comment/Post/', {
type: 'POST',
contentType: 'multipart/form-data',
// I have also use contentType: false,
processData: false,
data: formData
}).done(function (d) {
控制器: -
public Task<HttpResponseMessage> Post()
{
var provider = new MultipartMemoryStreamProvider();
var task1 = Request.Content.ReadAsMultipartAsync(provider);
var userId = User.Id;
return task1.Then(providerResult =>
{
var file = GetFileContent(providerResult);
var task2 = file.ReadAsStreamAsync();
string originalFileName = file.Headers.ContentDisposition.FileName.Replace("\"", "");
string extension = Path.GetExtension(originalFileName);
string fileName = Guid.NewGuid().ToString() + extension;
return task2.Then(stream =>
{
if (stream.Length > 0)
{
var kernel = WindsorContainerFactory.Create(KernelState.Thread, ConfigurationState.Web);
CloudBlobContainer container = GetContainer();
var userRepo = kernel.Resolve<IUserRepository>();
var logger = kernel.Resolve<ILogger>();
logger.Fatal("Original File Name: " + originalFileName);
logger.Fatal("Extension: " + extension);
logger.Fatal("File Name: " + fileName);
var user = userRepo.FirstOrDefault(x => x.Id == userId);
var path = CreateImageSize(stream, 500, fileName, userId, container, logger);
if (user != null)
{
user.AvatarOriginalFileName = fileName;
user.AvatarOriginalAbsolutePath =
ConfigurationManager.AppSettings["CdnUserEndpointUrl"] + path;
user.AvatarOriginalRelativePath = path;
user.AvatarCroppedAbsolutePath = "";
user.AvatarCroppedFileName = "";
user.AvatarCroppedRelativePath = "";
userRepo.Update(user);
}
else
{
Logger.Error("User is null. Id: " + userId.ToString());
}
kernel.Release(userRepo);
kernel.Release(logger);
kernel.Dispose();
}
var response = Request.CreateResponse(HttpStatusCode.Moved);
response.Headers.Location = new Uri("/Account/Avatar", UriKind.Relative);
return response;
});
});
}
以下错误获取: - “提供的'HttpContent'实例无效。它没有以'multipart /'开头的内容类型标题。参数名称:内容”
答案 0 :(得分:3)
.NET框架中没有标准的Task.Then
方法,我在您发布的代码中找不到任何实现细节。我假设它是从这里拿走的:
Processing Sequences of Asynchronous Operations with Tasks
如果是这种情况,您可能会在AspNetSynchronizationContext
lambdas中丢失Task.Then
上下文,因为如果没有正确的同步上下文,可能会在不同的ASP.NET池线程上发生延续。这可以解释为什么HttpContent
无效。
尝试更改Task.Then
的实现,如下所示:
public static Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, Task<T2>> next)
{
if (first == null) throw new ArgumentNullException("first");
if (next == null) throw new ArgumentNullException("next");
var tcs = new TaskCompletionSource<T2>();
first.ContinueWith(delegate
{
if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions);
else if (first.IsCanceled) tcs.TrySetCanceled();
else
{
try
{
var t = next(first.Result);
if (t == null) tcs.TrySetCanceled();
else t.ContinueWith(delegate
{
if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions);
else if (t.IsCanceled) tcs.TrySetCanceled();
else tcs.TrySetResult(t.Result);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
catch (Exception exc) { tcs.TrySetException(exc); }
}
}, TaskScheduler.FromCurrentSynchronizationContext());
return tcs.Task;
}
请注意现在如何使用TaskScheduler.FromCurrentSynchronizationContext()
安排续集。
理想情况下,如果您可以使用.NET 4.5,那么您应该使用async/await
:Using Asynchronous Methods in ASP.NET 4.5。这样,线程的同步上下文会自动捕获await
个连续。
以下可能是设施移植: Implementing Then with Await