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

Tyl*_*vey 7 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();
}
Run Code Online (Sandbox Code Playgroud)

Model正在从具有如下属性的ViewModel中提取:

    public System.DateTime? Birthday
    {
        get { return user.Birthday; }
        set { user.Birthday = value; }
    }
Run Code Online (Sandbox Code Playgroud)

抛出异常:

var today = new Date("@Model.Birthday.Value.Year", "@Model.Birthday.Value.Month" - 1, "@Model.Birthday.Value.Day");
Run Code Online (Sandbox Code Playgroud)

它返回"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为false.

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

Tom*_*mmy 5

我可以看到这里发生的几件事正在影响您呈现正确数据的能力。

首先,在服务器端处理MVC变量。您当前的实现始终在尝试为@Model.Birthday.ValueJavascript中的属性呈现值以生成HTML。在当前示例中,无论该属性为true还是false,都会发生这种情况,因为它依赖于客户端Javascript来执行条件而不是Razor。以下是您问题的完整工作示例。

查看模型

namespace MvcApplication1.Models
{
    public class TestViewModel
    {
        public DateTime? NullDate { get; set; }

        public DateTime? DateWithValue { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

控制者

public ActionResult Index()
        {
            return View(new TestViewModel{DateWithValue = DateTime.Now, 
NullDate = null});
            }
Run Code Online (Sandbox Code Playgroud)

视图

@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>
Run Code Online (Sandbox Code Playgroud)

现在,很明显,该代码在Javascript部分中进行了重复,以显示该代码可在同一控制器操作中同时适用于Null和Non-null值。

正如您在视图中所看到的,我们确保使用Razor语法检查Model和Javascript以设置实际的客户端变量。另外,我想知道您的“-1”是否工作正常。为了在此示例中进行减法,我不得不将该值从Javascript强制转换为Int,但这只是次要的细节。

作为参考,这是VS2012上的MVC 4项目,Windows 8 Professional已通过Chrome测试。


Rad*_*ler 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>
Run Code Online (Sandbox Code Playgroud)

详细说明:

找到答案让我们分一下上面的片段.它只是呈现HTML代码.让我们一步一步看

I. HasValue

@ Model.Birthday =新日期(2012,11,4)

1)Razor发送到Response流字符串,直到第一个@运算符

<script language="javascript" type="text/javascript">
var today;

if("
Run Code Online (Sandbox Code Playgroud)

2)这里Razor将此部分评估为@ Model.Birthday.HasValue作为布尔值并将其转换为字符串,因此代码的下一部分将是

True
Run Code Online (Sandbox Code Playgroud)

3)附加下一个直接字符串

"){
    var today = new Date("
Run Code Online (Sandbox Code Playgroud)

4)评估@ Model.Birthday.Value.Year并注入其字符串值

2012
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

II.Birthdate为NULL

如果@ Model.Birthday = null,则第一步1),2)和3)是相同的:

<script language="javascript" type="text/javascript">
    var today;

    if ("True"){
        var today = new Date("
Run Code Online (Sandbox Code Playgroud)

4)异常Nullable对象必须具有值

最后,还有一个我们得到Nullable异常的地方.

@ Model.Birthday.Value.Year

被称为

@ Model.Birthday == null