我正在尝试使用JQuery Form插件(http://jquery.malsup.com/form/)从我的视图上传文件和一些额外的字段,我希望action方法返回一个Json导致javascript回调。
目前,ActionMethod被正确调用(我可以处理表单中的文件和字段)但是当我返回Json结果时,浏览器会尝试将其作为文件下载(如果我下载文件并查看其内容,则为我要返回的JSON内容。)。
这是我的表格:
<form id="FormNewFile" action="@Url.Content("~/Home/AddFile")" method="post" enctype="multipart/form-data">
<input type="hidden" name="eventId" value="25" />
<input type="text" name="description" />
<input type="file" name="fileName" />
<input type="submit" value="Send!" />
</form>
这是我的javascript:
<script type="text/javascript">
$(function () {
$("#FormNewFile").ajaxForm({
dataType:'json',
success:processJson
});
});
function processJson(a,b) {
alert('success');
}
</script>
这是我的ActionMethod:
[HttpPost]
public ActionResult AddFile(long? eventId, string description)
{
int id = 5;
return Json(new {id});
}
浏览器尝试下载的文件名称类似于AddFilee87ce48e,最后8个字符是随机的十六进制字符。
最后,下载文件的内容是:
{ “ID”:5}
javascript中的processJson函数永远不会被调用。
我google了很多,似乎唯一有用的就是将JSON结果作为动作方法的“内容”结果返回,我认为这是我要采取的方法,但我仍然想知道为什么这样做不工作?
有什么想法吗?
答案 0 :(得分:10)
我最终做的是手动序列化我想要作为JSON返回的对象,如果我这样做,那么响应将没有标题,因此它将由javascript而不是浏览器处理。我使用了这个辅助方法:
public static ActionResult JsonPlain(object x)
{
var result = new ContentResult();
result.Content = new JavaScriptSerializer().Serialize(x);
return result;
}
希望这有助于其他人
答案 1 :(得分:4)
这是正常行为。 Excerpt from the documentation:
由于无法上传 使用浏览器的文件 XMLHttpRequest对象,Form Plugin 使用隐藏的iframe元素来提供帮助 有了这个任务。这是常见的 技术,但它有固有的 限制。 iframe元素是 用作表格的目标 提交操作意味着 服务器响应写入 iframe中。如果回复,这很好 type是HTML或XML,但不起作用 如果响应类型是脚本也是如此 或JSON,两者都经常包含 需要重复的字符 找到时使用实体引用 HTML标记。
应对挑战 脚本和JSON响应,表单 插件允许这些响应 嵌入textarea元素和它 建议你这样做 这些响应类型在使用时 与文件上传相结合。请 但请注意,如果没有 然后在表单中输入文件 请求使用普通XHR提交 形式(不是iframe)。这就是 要知道你的服务器代码的负担 什么时候使用textarea而不是 至。如果你愿意,你可以使用 插件的iframe选项强制 它总是使用iframe模式和 然后你的服务器可以随时嵌入 在textarea的回应。下列 响应显示脚本应该如何 从服务器返回:
这意味着如果要返回JSON,则需要将其包装在服务器上的<textarea>
标记中。为此,您可以编写一个源自JsonResult的自定义操作结果,并将生成的JSON包装在这些标记内。
答案 2 :(得分:1)
以下博客文章jQuery File Upload in ASP.NET MVC without using Flash解决了如Darin Dimitrov的回答所描述的在文本区域中包装响应的问题。
答案 3 :(得分:0)
查看表单标记上的操作:
action="@Url.Content("~/Home/AddFile")"
我见过的唯一用法是脚本标记,例如:
<script language="javascript" src="<%=Url.Content("~/Scripts/jquery-1.3.2.js")%>
该行动的正确参考将是:
action="/Home/Addfile"
虽然我不太清楚为什么只有UrlHelper的解释:
Url.Content("~/somepath")
将虚拟路径转换为绝对路径,并期望物理文件,例如javascript。
json结果可能作为文件下载返回,因为mvc框架期望文件下载某些描述。就像:
<a href="<%= Url.Content("~/_docs/folder/folder/document.pdf") %>">
document.pdf</a>
会下载或显示物理pdf文件。
答案 4 :(得分:0)
我的解决方案使用json而没有特定的javascript:
/// <summary>
/// A result to use in combination with jquery.ajax.form when we want to upload a file using ajax
/// </summary>
public class FileJsonResult : JsonResult
{
public JsonResult Result { get; set; }
public FileJsonResult(JsonResult result):base()
{
this.Result = result;
}
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.Write("<textarea>");
this.Result.ExecuteResult(context);
context.HttpContext.Response.Write("</textarea>");
context.HttpContext.Response.ContentType = "text/html";
}
}