从Javascript访问MVC的模型属性

时间:2013-05-03 14:32:01

标签: c# javascript jquery asp.net-mvc model

我有以下模型,它包含在我的视图模型中

public class FloorPlanSettingsModel
{
    public int Id { get; set; }
    public int? MainFloorPlanId { get; set; }
    public string ImageDirectory { get; set; }
    public string ThumbnailDirectory { get; set; }
    public string IconsDirectory { get; set; }
}

如何从Javascript访问上述某个属性?

我尝试了这个,但我得到了“未定义”

var floorplanSettings = "@Model.FloorPlanSettings";
alert(floorplanSettings.IconsDirectory);

9 个答案:

答案 0 :(得分:196)

您可以通过执行以下操作来获取整个服务器端模型并将其转换为Javascript对象:

var model = @Html.Raw(Json.Encode(Model));

在您的情况下,如果您只想要FloorPlanSettings对象,只需传递属性的Encode方法:

var floorplanSettings = @Html.Raw(Json.Encode(Model.FloorPlanSettings));

答案 1 :(得分:98)

  

答案的内容

     

1)如何在.cshtml文件中的Javascript / Jquery代码块中访问模型数据

     

2)如何在.js文件中的Javascript / Jquery代码块中访问模型数据

如何访问.cshtml文件中的Javascript / Jquery代码块中的模型数据

对JavaScript变量有两种类型的c#变量(Model)赋值。

  1. 属性分配 - 基本数据类型,例如intstringDateTime(例如:Model.Name
  2. 对象分配 - 自定义或内置类(例如:ModelModel.UserSettingsObj
  3. 让我们看一下这两个作业的细节。

    对于答案的其余部分,我们以下面的AppUser模型为例。

    public class AppUser
    {
        public string Name { get; set; }
        public bool IsAuthenticated { get; set; }
        public DateTime LoginDateTime { get; set; }
        public int Age { get; set; }
        public string UserIconHTML { get; set; }
    }
    

    我们为此模型分配的值是

    AppUser appUser = new AppUser
    {
        Name = "Raj",
        IsAuthenticated = true,
        LoginDateTime = DateTime.Now,
        Age = 26,
        UserIconHTML = "<i class='fa fa-users'></i>"
    };
    

    财产分配

    让我们使用不同的语法进行分配并观察结果。

    1)不用引号括起属性赋值。

    var Name = @Model.Name;  
    var Age = @Model.Age;
    var LoginTime = @Model.LoginDateTime; 
    var IsAuthenticated = @Model.IsAuthenticated;   
    var IconHtml = @Model.UserIconHTML;  
    

    enter image description here

    正如您所看到的,有几个错误,RajTrue被认为是javascript变量,因为它们不存在variable undefined错误。对于dateTime varialble,错误为unexpected number,数字不能包含特殊字符,HTML标记将转换为其实体名称,以便浏览器不会混淆您的值和HTML标记。

    2)在报价中包装属性。

    var Name = '@Model.Name';
    var Age = '@Model.Age';
    var LoginTime = '@Model.LoginDateTime';
    var IsAuthenticated = '@Model.IsAuthenticated';
    var IconHtml = '@Model.UserIconHTML'; 
    

    enter image description here

    结果有效,因此用引号包装属性赋值可以得到有效的语法。但请注意,数字Age现在是一个字符串,所以如果您不想要我们可以删除引号,它将呈现为数字类型。

    3)使用@Html.Raw,但不将其包装在引号

     var Name = @Html.Raw(Model.Name);
     var Age = @Html.Raw(Model.Age);
     var LoginTime = @Html.Raw(Model.LoginDateTime);
     var IsAuthenticated = @Html.Raw(Model.IsAuthenticated);
     var IconHtml = @Html.Raw(Model.UserIconHTML);
    

    enter image description here

    结果与我们的测试用例1类似。但是在@Html.Raw()字符串上使用HTML确实向我们展示了一些变化。保留HTML而不更改其实体名称。

    来自文档 Html.Raw()

      

    在HtmlString实例中包装HTML标记,以便将其解释为HTML标记。

    但我们在其他方面仍有错误。

    4)使用@Html.Raw并将其包装在引号

    var Name ='@Html.Raw(Model.Name)';
    var Age = '@Html.Raw(Model.Age)';
    var LoginTime = '@Html.Raw(Model.LoginDateTime)';
    var IsAuthenticated = '@Html.Raw(Model.IsAuthenticated)';
    var IconHtml = '@Html.Raw(Model.UserIconHTML)';
    

    enter image description here

    所有类型的结果都很好。但我们的HTML数据现在已被破坏,这将打破脚本。问题是因为我们使用单引号'来包装数据,甚至数据都有单引号。

    我们可以通过两种方法克服这个问题。

    1)使用双引号" "来包装HTML部分。由于内部数据只有单引号。 (确保在使用双引号包装后,数据中也没有"

      var IconHtml = "@Html.Raw(Model.UserIconHTML)";
    

    2)转义服务器端代码中的字符含义。像

      UserIconHTML = "<i class=\"fa fa-users\"></i>"
    

    财产分配的结论

    • 使用非数字dataType的引号。
    • 请勿对数字dataType使用引号。
    • 使用Html.Raw按原样解释您的HTML数据。
    • 处理您的HTML数据以转义服务器端的引号,或者在分配给javascript变量时使用与数据不同的引号。

    对象分配

    让我们使用不同的语法进行分配并观察结果。

    1)不用引号括起对象。

      var userObj = @Model; 
    

    enter image description here

    当您将c#对象分配给javascript变量时,将分配该对象的.ToString()的值。因此上述结果。

    2 在引号中包装对象

    var userObj = '@Model'; 
    

    enter image description here

    3)使用Html.Raw不带引号。

       var userObj = @Html.Raw(Model); 
    

    enter image description here

    4)使用Html.Raw和引号

       var userObj = '@Html.Raw(Model)'; 
    

    enter image description here

    在将对象分配给变量时,Html.Raw对我们没有多大用处。

    5)使用Json.Encode()不带引号

    var userObj = @Json.Encode(Model); 
    
    //result is like
    var userObj = {&quot;Name&quot;:&quot;Raj&quot;,
                   &quot;IsAuthenticated&quot;:true,
                   &quot;LoginDateTime&quot;:&quot;\/Date(1482572875150)\/&quot;,
                   &quot;Age&quot;:26,
                   &quot;UserIconHTML&quot;:&quot;\u003ci class=\&quot;fa fa-users\&quot;\u003e\u003c/i\u003e&quot;
                  };
    

    我们确实看到了一些变化,我们看到我们的模型被解释为一个对象。但我们将这些特殊字符更改为entity names。将上述语法包装在引号中也没什么用处。我们只是在引号内得到相同的结果。

    来自 Json.Encode()

    的文档
      

    将数据对象转换为JavaScript Object Notation(JSON)格式的字符串。

    由于您已经遇到了entity Name属性分配的问题,如果您还记得我们使用Html.Raw克服了它。所以让我们尝试一下。让我们结合Html.RawJson.Encode

    6)使用Html.RawJson.Encode不加引号。

    var userObj = @Html.Raw(Json.Encode(Model));
    

    结果是有效的 Javascript对象

     var userObj = {"Name":"Raj",
         "IsAuthenticated":true,
         "LoginDateTime":"\/Date(1482573224421)\/",
         "Age":26,
         "UserIconHTML":"\u003ci class=\"fa fa-users\"\u003e\u003c/i\u003e"
     };
    

    enter image description here

    7)在引号内使用Html.RawJson.Encode

    var userObj = '@Html.Raw(Json.Encode(Model))';
    

    enter image description here

    如您所见,用引号括起来会给我们一个 JSON数据

    对象分配的结论

    • 在合并中使用Html.RawJson.Encode将您的对象指定为javascript变量 JavaScript对象
    • 使用Html.RawJson.Encode也将其封装在quotes中以获得 JSON

    注意:如果您观察到DataTime数据格式不正确。这是因为如前所述Converts a data object to a string that is in the JavaScript Object Notation (JSON) format和JSON不包含date类型。解决此问题的其他选项是使用 javascipt Date() 对象添加另一行代码来单独处理此类型

    var userObj.LoginDateTime = new Date('@Html.Raw(Model.LoginDateTime)'); 
    //without Json.Encode
    

    如何访问.js文件中的Javascript / Jquery代码块中的模型数据

    Razor语法在.js文件中没有意义,因此我们无法直接使用我们的模型insisde .js文件。但是有一种解决方法。

    1)解决方案正在使用 javascript全局变量

    我们必须将值分配给全局范围的javascipt变量,然后在.cshtml.js文件的所有代码块中使用此变量。所以语法是

    <script type="text/javascript">
      var userObj = @Html.Raw(Json.Encode(Model)); //For javascript object
      var userJsonObj = '@Html.Raw(Json.Encode(Model))'; //For json data
    </script>
    

    有了这个,我们可以在需要时使用变量userObjuserJsonObj

    注意:我个人不建议使用全局变量,因为它很难维护。但是,如果您没有其他选项,那么您可以使用它具有正确的命名约定..类似userAppDetails_global

    2)使用功能()closure 在函数中包装所有依赖于模型数据的代码。然后从.cshtml文件中执行此函数。

    external.js

     function userDataDependent(userObj){
      //.... related code
     }
    

    .cshtml档案

     <script type="text/javascript">
      userDataDependent(@Html.Raw(Json.Encode(Model))); //execute the function     
    </script>
    

    注意:必须在上述脚本之前引用您的外部文件。否则userDataDependent函数未定义。

    另请注意,该功能也必须在全局范围内。因此,无论采用哪种解决方案,我们都必须与全球范围的玩家打交道。

答案 2 :(得分:18)

试试这个:(你错过了单引号)

var floorplanSettings = '@Html.Raw(Json.Encode(Model.FloorPlanSettings))';

答案 3 :(得分:3)

围绕parens包装模型属性对我有用。你仍然会在Visual Studio抱怨分号时遇到同样的问题,但它确实有效。

var closedStatusId = @(Model.ClosedStatusId);

答案 4 :(得分:1)

这就是我们在 .net core razor 页面中的做法。

@section scripts
{
    <script>
        $(document).ready(function () {
            leaveStatusDictionary = @Html.Raw(Json.Serialize(Model.LeaveStatusDictionary));
        });

        function GetStatusName(status) {
            return window.leaveStatusDictionary[status];
        }
    </script>
}

注意以下事项。

  1. 我在 leaveStatusDictionary 之前没有使用 var 关键字。所以这现在是 window 对象上的一个属性。所以我能够在不同的 js 函数中访问它 - 你在那里看到的 GetStatusName。

  2. LeaveStatusDictionary 是类型为 Dictionary 的模型类的一个属性。

答案 5 :(得分:0)

如果“ReferenceError:未定义模型”错误,则可能会尝试使用以下方法:

$(document).ready(function () {

    @{  var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
         var json = serializer.Serialize(Model);
    }

    var model = @Html.Raw(json);
    if(model != null && @Html.Raw(json) != "undefined")
    {
        var id= model.Id;
        var mainFloorPlanId = model.MainFloorPlanId ;
        var imageDirectory = model.ImageDirectory ;
        var iconsDirectory = model.IconsDirectory ;
    }
});

希望这会有所帮助......

答案 6 :(得分:0)

我知道它为时已晚,但是此解决方案对于.net框架和.net核心均适用:

@ System.Web.HttpUtility.JavaScriptStringEncode()

答案 7 :(得分:0)

对于 MVC 4

@model Inventory.Models.PurchaseVModel
@{
    ViewData["Title"] = "Add";
    Layout = "~/Views/Shared/_Layout.cshtml";
    var jsonItems = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model.Items);
}

@section scripts{
    <script>
        $(document).ready(function () {
            var allItem =  @Html.Raw(jsonItems);
        console.log(allItem);
    });
    </script>
}

.Net 核心 3.1

@model Inventory.Models.PurchaseVModel
@{
    ViewData["Title"] = "Add";
    Layout = "~/Views/Shared/_Layout.cshtml";
    var jsonItems = Newtonsoft.Json.JsonConvert.SerializeObject(Model.Items);
}

@section scripts{
    <script>
        $(document).ready(function () {
            var allItem =  @Html.Raw(jsonItems);
        console.log(allItem);
    });
    </script>
}

答案 8 :(得分:0)

除了@Rajshekar 详尽的 answer 之外,我更喜欢返回 IHtmlString 值的辅助方法,Razor 将其识别为已编码的 HTML。然后,不需要 Html.Raw() 包装器,从而提高可读性。

public static class JSHelper
{
    /// <summary>
    /// Encode a value as a JSON value or object for use in JavaScript code.
    /// </summary>
    /// <param name="value">Value to encode.</param>
    /// <returns>HTML string containing the JavaScript value or object.</returns>
    public static IHtmlString JsonEncode(object value)
    {
        return MvcHtmlString.Create(Json.Encode(value));
    }
}

然后我可以在 JavaScript 部分使用 obj = @JSHelper.JsonEncode(myObject);

在视图中包含 using 子句或更新 view/web.config 以解析视图中的命名空间。