I don't understand why a variable that I am setting on the model is coming down to the view, but not coming back up. Its 'feels' like a strange bug in HiddenFor()
I've written a simple example that reproduces the problem:
Model:
public class SampleModel
{
public string SpecialString { get; set; }
public string FileString { get; set; }
}
View:
@model FormResubmitTest.Test.SampleModel
....
@using (Html.BeginForm())
{
@Html.ValidationSummary(false)
if (@Model.FileString != null)
{
<p>@Model.FileString file exists</p>
}
<div>
@(Html.Kendo().Upload()
.Name("uploadDocument")
.Multiple(false)
.ShowFileList(true)
.Messages(o => o.Select("Select File To upload"))
)
</div>
@Html.HiddenFor(model => model.FileString)
@Html.TextBoxFor(model => model.SpecialString)
<input type="submit" name="submit" value="Submit" />
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new SampleModel(){});
}
[HttpPost]
public ActionResult Index(SampleModel model, HttpPostedFileBase uploadDocument)
{
if (uploadDocument != null)
{
model.FileString = SaveToTemporaryFile(uploadDocument);
}
if (model.SpecialString != "Special")
{
ModelState.AddModelError("SpecialString", "Special string was not special");
}
if (uploadDocument == null && model.FileString == null)
{
ModelState.AddModelError("FileString", "You have not uploaded a file");
}
if (ModelState.IsValid)
{
return RedirectToAction("Success");
}
return View(model);
}
public string SaveToTemporaryFile(HttpPostedFileBase file)
{
if (file == null)
{
return null;
}
var path = Path.GetTempPath();
var folder = Path.Combine(path, Guid.NewGuid().ToString());
Directory.CreateDirectory(folder);
var fileName = file.FileName;
fileName = System.IO.Path.GetFileName(fileName) ?? "file.txt";
var fullFileName = Path.Combine(folder, fileName);
using (FileStream fileStream = System.IO.File.Create(fullFileName, (int)file.InputStream.Length))
{
byte[] bytesInStream = new byte[file.InputStream.Length];
file.InputStream.Read(bytesInStream, 0, bytesInStream.Length);
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}
return fullFileName;
}
}
To see error:
- Upload a file
- Enter a string that is not "Special"
- Hit Submit
- It will now display the FileString correctly
- Enter "Special"
- Hit Submit
- The function Index will have a model with a blank FileString
I dont undertand why on the second call, the model has a blank filestring. Now if I look at the hidden for generated code its quite clear, the value is blank!
<input id="FileString" name="FileString" type="hidden" value="" />
I've put the full below, but why on earth is its value blank!!? We can see from the generated message; that the server is aware of it at generation.... I am so confused!
---EDIT---
I can make this work by doing this:
<input id="FileString" name="FileString" type="hidden" value="@Model.FileString" />
instead of
@Html.HiddenFor(model => model.FileString)
but it seems wrong that I have to do it like this
Does MVC (or the Html library I should say) somehow remember the original posted values? and uses them in the "Fors"