7

我对以下代码感到有些困惑。它在 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();
}

该模型是从具有如下属性的 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 object must have value”,如果它跳转到该行来执行它应该。但是,我的 if 语句返回错误。如果我删除该行并放入一个警报语句,它永远不会执行该行或显示警报,因为生日属性为空。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

4 回答 4

5

我可以看到这里发生的一些事情会影响您呈现正确数据的能力。

首先,MVC 变量在服务器端进行处理。您当前的实现总是尝试为@Model.Birthday.Value您的 Javascript 中的属性呈现一个值以生成 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 值。

正如您在视图中看到的,我们确保使用 Razor 语法检查模型,使用 Javascript 设置实际的客户端变量。另外,我想知道您的“- 1”是否正常工作。为了在本例中进行减法运算,我必须将该值从 Javascript 转换为 Int,但这是一个小细节。

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

于 2012-11-04T17:17:09.083 回答
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 正在发送到响应流字符串,直到第一个@运算符

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

二、生日为 NULL

如果 @Model.Birthday = null第一步 1)、2) 和 3) 相同:

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

    if ("True"){
        var today = new Date("

4) Exception Nullable 对象必须有值

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

@Model.Birthday.Value.Year

被称为 while

@Model.Birthday == null

于 2012-11-04T17:33:45.680 回答
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();
}
于 2012-11-04T13:21:29.423 回答
0

多行代码

@if ( Model.SomeProp == true)
{
  <text>
    <Your java script Multi-line  code>
  </text>
}

单行代码

@if ( Model.SomeProp == true)
{  
    @:<Your java script single-line code>  
}
于 2015-08-21T06:33:08.687 回答