jQuery ajax 表单文件上传到 .Net MVC,使用 InsertionMode.Replace 只能工作一次
我按照以下 url 中的示例进行操作,该示例演示了如何使用 jQuery Form 插件将异步文件上传到我的 .NET MVC 控制器。 ( http://aspzone.com /tech/jquery-file-upload-in-asp-net-mvc-without-using-flash/ )第一次一切都很好,在我第一次上传文件后,我替换了里面的 div表单通过返回的部分视图。当 div 被替换时,我调用一个 javascript 函数来重建 ajaxForm 对象,但这似乎是事情停止工作的地方。当代码第一次返回时,我得到了替换的 div ,并且外观正确,但 javascript 代码似乎没有将 ajaxForm 对象附加回替换的 div 中存在的表单。这意味着我第二次使用表单发布时,它会将用户重定向到页面之外。我想说这是控制器中的缓存问题,但我得到的响应显示了 ascx 中更新的项目列表。最后一件事,当我查看 IE 开发工具栏中的 dom 元素时,我看到一个类似于“jQuery16404440065521567182”的属性,其值为 33,并且在第一次提交后消失。我猜这是由 ajaxForm 放在那里的。这是我正在使用的代码(更改了一些 javascript 命名空间以删除项目特定命名):
ASCX 文件
<!-- Form to add a new record -->
<% using (Html.BeginForm("SaveAttachment", "Report", FormMethod.Post, new { enctype = "multipart/form-data", id = "AttachmentForm" })) { %>
<input type="hidden" name="ReportId" value="<%: Model.ReportId %>" />
<input type="file" name="FileUpload" value="" size="21" />
<label for="Title">
Title:</label>
<input type="text" name="Title" value="" />
<input type="submit" value="Add" class="inputButton" />
<% } %>
<!-- Display existing items -->
<% foreach (var item in Model.ExistingAttachments) { %>
<div>
<%: item.Sort %> <%: item.Title.PadRight(25, ' ').Substring(0, 25).TrimEnd() %></div>
<% } %>
ASPX 文件
<div id="AttachmentsWindow">
<% Html.RenderPartial("LoadAttachments", Model.ReportAttachments); %>
</div>
<!-- This form is used to refresh the above div -->
<% using (Ajax.BeginForm("LoadAttachments", new { ReportId = Model.ReportId },
new AjaxOptions {
HttpMethod = "Post",
LoadingElementId = "LoadingAttachments",
UpdateTargetId = "AttachmentsWindow",
InsertionMode = InsertionMode.Replace,
OnComplete = "Report.InitAttachment"
}, new { id = "LoadAttachmentsForm" })) { %>
<input type="submit" name="submit" value="" class="button" style="float:right;"
onmouseover="this.className='button buttonhov'" onmouseout="this.className='button'"/>
<% } %>
控制器
[HttpPost]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public FileUploadJsonResult SaveAttachment(ReportAttachmentViewModel Attachment) {
if ( Attachment.FileUpload.ContentLength < 1 ){
return new FileUploadJsonResult { Data = new { message = "No file chosen." } };
}
var Report = this._reportRepository.GetById(Attachment.ReportId);
if (Report == null)
throw new Exception("Report not found");
MemoryStream target = new MemoryStream();
Attachment.FileUpload.InputStream.CopyTo(target);
byte[] data = target.ToArray();
ReportAttachment newobj = new ReportAttachment {
Attachment = data,
Description = string.Empty,
Name = Attachment.Title,
Report = Report,
ReportId = Report.Id
};
var result = this._reportAttachmentRepository.Add(ref newobj);
Report.ReportAttachments.Add(newobj);
ModelState.Clear();
if (!result.Success) {
StringBuilder sb = new StringBuilder();
foreach (var msg in result.Messages) {
sb.AppendLine(string.Format("{0}", msg.Message));
}
return new FileUploadJsonResult { Data = new { message = sb.ToString() } };
}
return new FileUploadJsonResult { Data = new { message = string.Format("{0} uploaded successfully.", System.IO.Path.GetFileName(Attachment.FileUpload.FileName)) } };
Javascript
//Report namespace
InitAttachment: function () {
jQuery('#AttachmentForm').ajaxForm({
iframe: true,
dataType: "json",
beforeSubmit: function () {
jQuery('#AttachmentForm').block({ message: 'Uploading File... ' });
},
success: function (result) {
jQuery('#AttachmentForm').unblock();
jQuery('#AttachmentForm').resetForm();
$.growlUI(null, result.message);
Editor.EndLoading(false, false, true);
},
error: function (xhr, textStatus, errorThrown) {
$("#ajaxUploadForm").unblock();
$("#ajaxUploadForm").resetForm();
$.growlUI(null, 'Error uploading file');
}
});
//Editor namespace
EndLoading: function (ReloadReportSections, ReloadReferences, ReloadAttachments) {
//Reload sections
if (ReloadReportSections)
jQuery('#LoadReportSectionsForm').submit();
if (ReloadReferences)
jQuery('#LoadReferencesForm').submit();
if (ReloadAttachments) {
jQuery('#LoadAttachmentsForm').submit();
}
//endReload
Report.InitAttachment();
//Close the loading dialog
jQuery('#LoadingWindow').dialog('close');
}
I followed an example from the following url that shows how to use the jQuery Form plugin to do an async file upload to my .NET MVC controller. ( http://aspzone.com/tech/jquery-file-upload-in-asp-net-mvc-without-using-flash/ ) Everything works completely great the first time and after I upload a file the first time I am replacing the div inside which the form sits via a returned PartialView. When the div is replaced I then call a javascript function to rebuild the ajaxForm object but that seems to be where things stop working. When the code returns the first time I get my replaced div just fine and the appearance is proper, but the javascript code does not seem to be attaching the ajaxForm object back to the form that exists inside the replaced div. This means that the second time I post with the form, it redirects the user away from the page. I would love to say it's a caching issue in the controller, but the response I get shows the updated list of items in the ascx. One last thing, when I look at the dom element in the IE dev toolbar I see an attribute like "jQuery16404440065521567182" with a value of 33 and that disappears after the first submit. I'm guessing that is put there by the ajaxForm. Here is the code I am using ( some of the javascript namespacing was changed to remove project specific naming ):
ASCX file
<!-- Form to add a new record -->
<% using (Html.BeginForm("SaveAttachment", "Report", FormMethod.Post, new { enctype = "multipart/form-data", id = "AttachmentForm" })) { %>
<input type="hidden" name="ReportId" value="<%: Model.ReportId %>" />
<input type="file" name="FileUpload" value="" size="21" />
<label for="Title">
Title:</label>
<input type="text" name="Title" value="" />
<input type="submit" value="Add" class="inputButton" />
<% } %>
<!-- Display existing items -->
<% foreach (var item in Model.ExistingAttachments) { %>
<div>
<%: item.Sort %> <%: item.Title.PadRight(25, ' ').Substring(0, 25).TrimEnd() %></div>
<% } %>
ASPX file
<div id="AttachmentsWindow">
<% Html.RenderPartial("LoadAttachments", Model.ReportAttachments); %>
</div>
<!-- This form is used to refresh the above div -->
<% using (Ajax.BeginForm("LoadAttachments", new { ReportId = Model.ReportId },
new AjaxOptions {
HttpMethod = "Post",
LoadingElementId = "LoadingAttachments",
UpdateTargetId = "AttachmentsWindow",
InsertionMode = InsertionMode.Replace,
OnComplete = "Report.InitAttachment"
}, new { id = "LoadAttachmentsForm" })) { %>
<input type="submit" name="submit" value="" class="button" style="float:right;"
onmouseover="this.className='button buttonhov'" onmouseout="this.className='button'"/>
<% } %>
Controller
[HttpPost]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public FileUploadJsonResult SaveAttachment(ReportAttachmentViewModel Attachment) {
if ( Attachment.FileUpload.ContentLength < 1 ){
return new FileUploadJsonResult { Data = new { message = "No file chosen." } };
}
var Report = this._reportRepository.GetById(Attachment.ReportId);
if (Report == null)
throw new Exception("Report not found");
MemoryStream target = new MemoryStream();
Attachment.FileUpload.InputStream.CopyTo(target);
byte[] data = target.ToArray();
ReportAttachment newobj = new ReportAttachment {
Attachment = data,
Description = string.Empty,
Name = Attachment.Title,
Report = Report,
ReportId = Report.Id
};
var result = this._reportAttachmentRepository.Add(ref newobj);
Report.ReportAttachments.Add(newobj);
ModelState.Clear();
if (!result.Success) {
StringBuilder sb = new StringBuilder();
foreach (var msg in result.Messages) {
sb.AppendLine(string.Format("{0}", msg.Message));
}
return new FileUploadJsonResult { Data = new { message = sb.ToString() } };
}
return new FileUploadJsonResult { Data = new { message = string.Format("{0} uploaded successfully.", System.IO.Path.GetFileName(Attachment.FileUpload.FileName)) } };
Javascript
//Report namespace
InitAttachment: function () {
jQuery('#AttachmentForm').ajaxForm({
iframe: true,
dataType: "json",
beforeSubmit: function () {
jQuery('#AttachmentForm').block({ message: 'Uploading File... ' });
},
success: function (result) {
jQuery('#AttachmentForm').unblock();
jQuery('#AttachmentForm').resetForm();
$.growlUI(null, result.message);
Editor.EndLoading(false, false, true);
},
error: function (xhr, textStatus, errorThrown) {
$("#ajaxUploadForm").unblock();
$("#ajaxUploadForm").resetForm();
$.growlUI(null, 'Error uploading file');
}
});
//Editor namespace
EndLoading: function (ReloadReportSections, ReloadReferences, ReloadAttachments) {
//Reload sections
if (ReloadReportSections)
jQuery('#LoadReportSectionsForm').submit();
if (ReloadReferences)
jQuery('#LoadReferencesForm').submit();
if (ReloadAttachments) {
jQuery('#LoadAttachmentsForm').submit();
}
//endReload
Report.InitAttachment();
//Close the loading dialog
jQuery('#LoadingWindow').dialog('close');
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可能需要在调用
ajaxForm()
之前删除InitAttachment()
中隐藏的iframe
(如果存在)。如果先前上传的 iframe 仍然存在,听起来文件上传表单的目标可能会变得混乱。
我在 ExtJS 中遇到过类似的问题,但不能说它是一样的。
You might want to remove the hidden
iframe
(if it exists) inInitAttachment()
before callingajaxForm()
.It sounds like the target of the file upload form might getting messed up, if the
iframe
from a previous upload is still there.I've fought with similar issues in
ExtJS
, can't say it's the same though.事实证明,是我在错误的位置调用了更新。在我看来,
OnSuccess
会在OnComplete
之前触发,但在 MS Ajax 模型中却不会。OnSuccess
正在被调用,看起来它正在影响代码,因为它命中了我设置的所有断点,但在调用替换逻辑之前它一定已经命中了旧的 DOM 元素。我似乎找不到任何讨论发生这种情况的顺序的文档,但我注意到当我从AjaxOptions.OnSuccess
属性调用.ajaxForm
时,一切正常。简而言之,我的建议是:使用
AjaxOptions.OnSuccess
和AjaxOptions.OnFailed
来影响更新的 DOM,但如果需要临时逻辑,则使用AjaxOptions.OnComplete
。It turns out that it was that I am calling the update in the wrong location. In my mind I would imagine that
OnSuccess
would fire beforeOnComplete
, but in the MS Ajax model it does not.OnSuccess
was being called and it looked like it was affecting the code because it was hitting all the breakpoints I had set, but it must have been hitting the old DOM element before the Replace logic was called. I cannot seem to find any documentation that talks about the order in which this occurs, but I noticed that when I call.ajaxForm
from theAjaxOptions.OnSuccess
property everything works well. So my suggestion in short:Use
AjaxOptions.OnSuccess
andAjaxOptions.OnFailed
to affect the updated DOM butAjaxOptions.OnComplete
if you need interim logic.