Javascript在If语句中错误地执行MVC代码

时间:2012-11-04 13:04:03

标签: javascript asp.net-mvc internet-explorer-10

我对以下代码感到有点难过。它在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语句如何,它都会评估整个代码块。我也试过以下,但无济于事:

  • 在Chrome for W8中测试
  • 在try / catch块中测试。有趣的是,它没有捕获异常(我猜JS不会捕获.NET异常)
  • 通过明确说明@ Model.Birthday.HasValue == true
  • 进行测试
  • 通过将其更改为@ Model.Birthday.Value!= null
  • 进行测试
  • 通过调试模式在发布模式下测试

这应该很简单 - 测试一个值是否为null,如果不是,则从.NET属性创建一个JS Date对象,如果是,则创建一个新的JS Date对象,但由于某种原因,它想要评估并执行该行,即使HasValue为假。

真的很难过。有没有人见过这样的东西?

4 个答案:

答案 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代码。让我们一步一步地看到它

予。的HasValue

@ 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>

II。 Birthdate为NULL

如果@ 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>  
}