繁体   English   中英

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

[英]Javascript executing MVC code in If statement incorrectly

我对以下代码感到有点难过。 它在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为false。

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

解决方案简而言之:

我测试了你的代码,可以说,你的硬件/软件更新没有问题。 我正在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代码。 让我们一步一步看

I. HasValue

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

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

<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

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

首先,在服务器端处理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。

问题是你混淆了客户端代码和服务器端代码。 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();
}

多行代码

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

单行代码

@if ( Model.SomeProp == true)
{  
    @:<Your java script single-line code>  
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM