我对以下代码感到有点难过。它在Windows 7上的VS2010中运行良好,现在我已经将硬件升级到Windows 8和VS 2012,但事实并非如此。
我的MVC应用程序中有以下JavaScript代码:
<script language="javascript" type="text/javascript">
var today;
if("@Model.Birthday.HasValue"){
var today = new Date("@Model.Birthday.Value.Year", "@Model.Birthday.Value.Month" - 1, "@Model.Birthday.Value.Day");
}else{
today = new Date();
}
Model正在从具有如下属性的ViewModel中提取:
public System.DateTime? Birthday
{
get { return user.Birthday; }
set { user.Birthday = value; }
}
行中会抛出异常:
var today = new Date("@Model.Birthday.Value.Year", "@Model.Birthday.Value.Month" - 1, "@Model.Birthday.Value.Day");
它返回“Nullable对象必须具有值”,如果它在该行中跳转以执行它应该返回。但是,我的if语句返回false。如果我删除该行并只是放入一个警告语句,它永远不会执行该行或显示警报,因为Birthday属性为null。似乎JS在执行MVC代码方面发生了变化,似乎无论if语句如何,它都会评估整个代码块。我也试过以下,但无济于事:
这应该很简单 - 测试一个值是否为null,如果不是,则从.NET属性创建一个JS Date对象,如果是,则创建一个新的JS Date对象,但由于某种原因,它想要评估并执行该行,即使HasValue为假。
真的很难过。有没有人见过这样的东西?
答案 0 :(得分:5)
解决方案简而言之:
我测试了您的代码,可以说,您的硬件/软件更新没有问题。我在Win 7上运行VS 2010。 解决方案可能是 以这种方式更改代码
<script language="javascript" type="text/javascript">
@{ // C# server side part to get the dateParameters
var dateParameters = string.Empty;
if (Model.Birthday.HasValue)
{
dateParameters = "" + @Model.Birthday.Value.Year
+ ", " + (@Model.Birthday.Value.Month - 1)
+ ", " + @Model.Birthday.Value.Day;
}
}
// JS client side, later working with just created dateParameters
var today = new Date(@dateParameters);
alert(today);
</script>
详细说明:
找到答案让我们分一下上面的代码片段。 只是呈现HTML代码。让我们一步一步地看到它
@ Model.Birthday =新日期(2012,11,4)
1)Razor发送到Response stream字符串,直到第一个 @ 运算符
<script language="javascript" type="text/javascript">
var today;
if("
2)这里Razor评估这部分 @ Model.Birthday.HasValue作为布尔值并将其转换为字符串,因此代码的下一部分将是
True
3)附加下一个直接字符串
"){
var today = new Date("
4)评估@ Model.Birthday.Value.Year并注入其字符串值
2012
5)6)7)......等等 发送给Response的最终结果是:
<script language="javascript" type="text/javascript">
var today;
if ("True"){
var today = new Date("2012", "11" - 1, "4");
} else{
today = new Date();
}
</script>
如果@ Model.Birthday = null ,第一步1),2)和3)是相同的:
<script language="javascript" type="text/javascript">
var today;
if ("True"){
var today = new Date("
4)异常 Nullable对象必须具有值
最后,我们可以获得Nullable异常。
@ Model.Birthday.Value.Year
时调用
@ Model.Birthday == null
答案 1 :(得分:4)
我可以看到这里发生的一些事情影响了你呈现正确数据的能力。
首先,在服务器端处理MVC变量。您当前的实现始终尝试为Javascript中的@Model.Birthday.Value
属性呈现值以生成HTML。无论当前示例中的属性是true还是false,都会发生这种情况,因为它依赖于客户端Javascript来执行条件而不是Razor。以下是您的问题的完整工作示例。
查看模型
namespace MvcApplication1.Models
{
public class TestViewModel
{
public DateTime? NullDate { get; set; }
public DateTime? DateWithValue { get; set; }
}
}
<强>控制器强>
public ActionResult Index()
{
return View(new TestViewModel{DateWithValue = DateTime.Now,
NullDate = null});
}
查看强>
@model MvcApplication1.Models.TestViewModel
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<script type="text/javascript">
var today;
var anotherDay;
@{if(Model.NullDate.HasValue)
{
@: alert('Null date had a value!');
@: today = new Date('@Model.NullDate.Value.Year', parseInt('@Model.DateWithValue.Value.Month') - 1, '@Model.NullDate.Value.Day');
}else
{
@: alert('Null date did not have a value');
@: today = new Date();
}}
@{if (Model.DateWithValue.HasValue)
{
@: alert('DateWithValue had a value!');
@: anotherDay = new Date('@Model.DateWithValue.Value.Year', parseInt('@Model.DateWithValue.Value.Month') - 1, '@Model.DateWithValue.Value.Day');
@: alert(anotherDay);
}
else
{
@: alert('DateWithValue date did not have a value');
@: anotherDay = new Date();
}}
</script>
现在显然,代码在Javascript部分中重复,以便显示它适用于同一控制器操作中的Null和Non-null值。
正如您在View中看到的那样,我们确保使用Razor语法检查Model和Javascript以设置实际的客户端变量。另外,我想知道你的' - 1'是否正常工作。为了在这个例子中进行减法,我不得不从Javascript中将该值转换为Int,但这是一个小细节。
作为参考,这是VS2012上的MVC 4项目,使用Chrome测试了Windows 8 Professional。
答案 2 :(得分:1)
问题是你混淆了客户端代码和服务器端代码。 javascript在客户端运行,但只在所有服务器端代码完成后才运行。
所以@ Model.Birthday.HasValue,@ Model.Birthday.Value.Year等都将在服务器端进行评估,然后才能到达浏览器附近。 javascript代码(因此在这种情况下,if语句)将永远不会到达浏览器,因为异常发生在服务器端,尝试在null对象上评估Model.Birthday.Value.Year。
您需要移动条件服务器端,例如
@if(Model.Birthday.HasValue){
@:today = new Date(@(Model.Birthday.Value.Year), @(Model.Birthday.Value.Month) - 1, @(Model.Birthday.Value.Day));
} else {
@:today = new Date();
}
答案 3 :(得分:0)
多行代码
@if ( Model.SomeProp == true)
{
<text>
<Your java script Multi-line code>
</text>
}
单行代码
@if ( Model.SomeProp == true)
{
@:<Your java script single-line code>
}