在我的MVC应用程序中,当发布的模型无效时,我希望模型状态保存到TempData
,以便在重定向到另一个操作时显示。
这是我做的:
if (!ModelState.IsValid)
{
TempData["ViewData"] = ViewData;
return RedirectToAction("Edit", new { id = model.Id });
}
重定向到:
public ActionResult Edit(Guid id)
{
var model = Services.Get(id);
if (TempData["ViewData"] != null)
{
ViewData = (ViewDataDictionary)TempData["ViewData"];
}
ViewBag.HasUpdated = TempData["HasUpdated"];
return View(model);
}
它在localhost中工作正常,但在服务器上失败了。
错误消息告诉:
无法序列化会话状态。在' StateServer'和' SQLServer'在模式下,ASP.NET将序列化会话状态对象,因此不允许使用不可序列化的对象或MarshalByRef对象。如果自定义会话状态存储在'自定义'中进行类似的序列化,则适用相同的限制。模式。
由于我们的服务器使用SQL Server会话模式,通常,当我们想要将某些模型保存到Session中时,我们在模型的开头添加[Serializable]
。但是我们可以对ViewData
做些什么呢?如何将 ViewDataDictionary 保存到我们的会话中?
答案 0 :(得分:0)
您无法将ViewData或ViewDataDictionary存储在SQL Server会话状态中,因为它们不可序列化,也不确定您放入其中的数据是否可序列化。
如果本地应用程序配置为使用SQL Server作为会话状态存储,您应该能够看到相同的错误。
不是直接在会话状态中存储ViewData,而是应该从viewdata中获取实际对象,然后将该对象存储到会话状态。如果该对象的类型不可序列化,问题仍然会持续存在。
如果要存储modelstate,可以创建类来存储它。
[Serializable]
public class ModelStateStore
{
public List<ModelStateData> {get;set;}
}
[Serializable]
public class ModelStateData
{
public string PropertyName {get;set;}
public bool IsValid {get;set;}
public string ErrorMessage {get;set;}
}
您可以使用此数据结构存储模型状态信息并将其存储在会话中。并在需要时从会话中检索它并检索它并创建新的模型状态。
因此,简而言之,您无法在Sql Server会话状态中存储任何内容。您需要确保存储的值符合条件。
答案 1 :(得分:0)
这是一个详细的解决方案,灵感来自Chetan Ranpariya的答案。
可存储在会话中的可序列化模型。
SELECT sle.source_id,
count(sle.*),
sum(coalesce(log_field20::numeric, 0)) || ' min' as duration_total
FROM custom_field_log_entries sle
INNER JOIN student_enrollment se
ON (sle.source_id=se.student_id and se.custom_9 is null
AND se.syear = {SYEAR}
AND se.end_date is null)
INNER JOIN schools sc on (se.school_id=sc.id)
WHERE sle.field_id = 328
**AND log_field2::date BETWEEN '{START_DATE}' AND '{END_DATE}'**
AND (log_field20 ~ '^[0-9]+$' or log_field20 is null) --{SCHOOL_SPECIFIC}
AND se.school_id = {SCHOOL_ID}
GROUP BY sle.source_id
一些扩展方法。
[Serializable]
public class ModelStateSummary
{
public string PropertyName { get; set; }
public string[] ErrorMessages { get; set; }
}
将模型状态设置为会话变量:
public static class ModelStateExtensions
{
public static IEnumerable<ModelStateSummary> ToSummary(this ModelStateDictionary modelState)
{
return modelState.Select(state => new ModelStateSummary
{
PropertyName = state.Key,
ErrorMessages = state.Value.Errors.Select(x => x.ErrorMessage).ToArray()
});
}
public static ModelStateDictionary ToModelState(this IEnumerable<ModelStateSummary> summary)
{
var modelStates = new ModelStateDictionary();
foreach (var modelState in summary)
{
var data = new ModelState();
foreach (var errorMessage in modelState.ErrorMessages)
{
data.Errors.Add(new ModelError(errorMessage));
}
modelStates.Add(modelState.PropertyName, data);
}
return modelStates;
}
}
重定向后,在目标操作上,检查会话变量并转移到if (!ModelState.IsValid)
{
Session["ModelStateSummary"] = ModelState.ToSummary();
return RedirectToAction("Edit");
}
。
ViewData.ModelState
通过这种方式,我们将if (Session["ModelStateSummary"] != null)
{
var stateSummaries = (List<ModelStateSummary>)Session["ModelStateSummary"];
ModelState.Merge(stateSummaries.ToModelState());
}
从一个操作转移到另一个操作。