現在、MVC3 で最初のアプリケーションを構築しています。私の見解の 1 つでは、2 つの形式があります。1つは、画像を選択し、AJAXを使用してページに表示/アップロードするだけです(別のコントローラーを呼び出し、この投稿のように非表示のIFrameを使用します)。もう 1 つのフォームは、名前、住所などの情報を入力するためのものです。また、最初のフォームを使用して画像を選択してインポートすると、2 番目のフォームに隠しフィールドが入力され、Create コントローラーが呼び出されたときにすべてが作成されます。データベースで。
これはすべて完全に機能しますが、ユーザーが間違いを犯して 2 番目のフォームの数値フィールドにテキストを入力すると、モデルの検証が行われ、エラーを赤で示すポストバックが表示されます。そうすることで、最初のフォームはすべての情報を失い、ファイル入力コントロールでリセットされ、画像は表示されません。
この問題を回避する方法を知っている人はいますか? 私はMVC3とAJAXに非常に慣れていないので、何か間違っているかもしれません。
私の最終的な目標は、画像がページに表示される (およびアップロードされる) と、2 番目のフォームが検証されて Create コントローラーに送信されるまでそこにとどまることです。
ありがとう!
編集: コードを要求する人もいますが、ここにあります! これはビューです:
@model RecettesMaison.Models.Recipe
@{
ViewBag.Title = "Create";
}
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.min.js" type="text/javascript"></script>
<script type="text/javascript">
var isFirstLoad = true;
var loadingImg;
function UploadImage() {
var fileUploader = document.getElementById("fileuploader");
$(fileUploader).hide();
//Create a new image and insert it into the Images div. Just to be fancy,
//we're going to use a "FadeIn" effect from jQuery
var imgDiv = document.getElementById("Images");
loadingImg = new Image();
loadingImg.src = "../../Pictures/ajax-loader.gif";
//Hide the image before adding to the DOM
$(loadingImg).hide();
imgDiv.appendChild(loadingImg);
//Now fade the image in
$(loadingImg).fadeIn(500, null);
$("#ImgForm").submit();
}
function UploadImage_Complete() {
//Check to see if this is the first load of the iFrame
if (isFirstLoad == true) {
isFirstLoad = false;
return;
}
//Reset the image form so the file won't get uploaded again
document.getElementById("ImgForm").reset();
//Grab the content of the textarea we named jsonResult . This shold be loaded into
//the hidden iFrame.
var newImg = $.parseJSON($("#UploadTarget").contents().find("#jsonResult")[0].innerHTML);
//If there was an error, display it to the user
if (newImg.IsValid == false) {
alert(newImg.Message);
return;
}
//Create a new image and insert it into the Images div. Just to be fancy,
//we're going to use a "FadeIn" effect from jQuery
var imgDiv = document.getElementById("Images");
var img = new Image();
img.src = newImg.ImagePath;
img.name = "uploadedImage";
var input = document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", "Picture");
input.setAttribute("id", "Picture");
input.setAttribute("value", newImg.RealName);
document.getElementById("Hidden").appendChild(input);
//Hide the image before adding to the DOM
$(img).hide();
imgDiv.removeChild(loadingImg)
imgDiv.appendChild(img);
$(img).addClass('img-polaroid');
//Now fade the image in
$(img).fadeIn(500, null);
}
</script>
<iframe id="UploadTarget" name="UploadTarget" onload="UploadImage_Complete();" style="position: absolute; left: -999em; top: -999em;"></iframe>
<fieldset>
<div class="row-fluid">
<div class="span12">
<h4>Publier une recette</h4>
<div class="row-fluid">
<div class="span3">
@using (Html.BeginForm("UploadImage", "Recipe", FormMethod.Post,
new
{
enctype = "multipart/form-data",
id = "ImgForm",
name = "ImgForm",
target = "UploadTarget"
}))
{
<div id="fileuploader">
<input id="lefile" type="file" style="display:none" name="imageFile" accept="image/x-png, image/jpeg" />
<div class="input-append">
<input id="photoCover" class="input-large" type="text" />
<a class="btn" onclick="$('input[id=lefile]').click();">Parcourir...</a>
</div>
<script type="text/javascript">
$('input[id=lefile]').change(function () {
$('#photoCover').val($(this).val());
});
</script>
<input type="button" class="btn btn-success" value="Sauvegarder l'image" onclick="UploadImage()" />
</div>
<div id="Images"></div>
}
</div>
<div class="span9">
@using (Html.BeginForm("Create", "Recipe", FormMethod.Post, new { id = "realForm", name = "realform" }))
{
@Html.ValidationSummary(true)
<div id="Hidden"></div>
<div class="editor-label">
@Html.LabelFor(model => model.RecipeName) <div class="alert alert-info">Soyez original!</div>
</div>
<div class="editor-field">
@Html.EditorFor(model => model.RecipeName)
@Html.ValidationMessageFor(model => model.RecipeName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Source) <div class="alert alert-info">(Exemple: Ricardo, Food Channel, Blog de Jean Cuisine, etc...)</div>
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Source)
@Html.ValidationMessageFor(model => model.Source)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.PreparationTime)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.PreparationTime) minutes
@Html.ValidationMessageFor(model => model.PreparationTime)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.CookingTime)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.CookingTime) minutes
@Html.ValidationMessageFor(model => model.CookingTime)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.MacerationTime)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.MacerationTime) minutes
@Html.ValidationMessageFor(model => model.MacerationTime)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Portions) <div class="alert alert-info">Combien d'adultes cette recettes peut nourir?</div>
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Portions)
@Html.ValidationMessageFor(model => model.Portions)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Commentary) <div class="alert alert-info">Partagez votre expérience avec cette recette, que ce soit au moment de sa création ou de sa préparation. <br />Dites les modifications que vous faites à la recette originale.<br />Rendez cette recettes personnelle! </div>
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Commentary)
@Html.ValidationMessageFor(model => model.Commentary)
</div>
<p>
<input type="submit" class="btn btn-success" value="Publier la recette!" />
</p>
}
</div>
</div>
</div>
</div>
</fieldset>
画像送信用コントローラーはこちら
[HttpPost]
public WrappedJsonResult UploadImage(HttpPostedFileWrapper imageFile)
{
if (imageFile == null || imageFile.ContentLength == 0)
{
return new WrappedJsonResult
{
Data = new
{
IsValid = false,
Message = "No file was uploaded.",
ImagePath = string.Empty
}
};
}
if (imageFile.ContentType != "image/jpeg" && imageFile.ContentType != "image/png")
{
return new WrappedJsonResult
{
Data = new
{
IsValid = false,
Message = "Mauvais format de fichier!",
ImagePath = string.Empty
}
};
}
int nIndexPoint = imageFile.FileName.IndexOf(".");
string strExtension = imageFile.FileName.Substring(nIndexPoint + 1);
var fileName = String.Format("{0}.{1}", Guid.NewGuid().ToString(), strExtension);
var imagePathFull = Path.Combine(Server.MapPath(Url.Content("~/Pictures/Upload/FullSize")), fileName);
var imagePathThumb = Path.Combine(Server.MapPath(Url.Content("~/Pictures/Upload/Thumbnail")), fileName);
imageFile.SaveAs(imagePathFull);
ThumbnailGenerator generator = new ThumbnailGenerator();
generator.GetThumbnail(imagePathFull, imagePathThumb);
return new WrappedJsonResult
{
Data = new
{
IsValid = true,
Message = string.Empty,
ImagePath = Url.Content(String.Format("~/Pictures/Upload/Thumbnail/{0}", fileName)),
RealName = fileName
}
};
}
最後に、2 番目のフォームによって呼び出されるコントローラーを次に示します。
[HttpPost]
public ActionResult Create(Recipe recipe)
{
if (ModelState.IsValid)
{
db.Recipes.Add(recipe);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(recipe);
}