从 ASP.NET MVC 复杂模型创建 KnockoutJS 模型

Posted

技术标签:

【中文标题】从 ASP.NET MVC 复杂模型创建 KnockoutJS 模型【英文标题】:Creating a KnockoutJS Model From an ASP.NET MVC complex model 【发布时间】:2014-01-31 05:42:29 【问题描述】:

我想使用 ko.mapping.fromJS() 方法从 asp.net MVC 模型创建淘汰视图模型,但我的表单没有填充值。

鉴于我创建的脚本如下所示:

   <script type="text/javascript">
            var tmp = @html.Raw(Model.ToJson());
            var viewModel = ko.mapping.fromJS(tmp);
            ko.applyBindings(viewModel);
    </script>

@Html.Raw(Model.ToJson() 返回值

 "id":1,
"surveyCode":null,
"title":"Życie",
"description":"Ankieta, w której zadawane będą pytania na temat codziennego życia ",
"dateStart":"2013-12-12T00:00:00",
"dateEnd":"2014-12-30T00:00:00",
"createDate":"2014-01-07T03:23:16.053",
"lastModification":"2014-01-07T03:23:16.053",
"isActive":false,
"questions":["id":1,
            "surveyID":1,
            "content":"Co jesz na śniadanie?",
            "tips":"wybierz jedną odpowiedź",
            "questionType":1,
            "isRequired":true,
            "answers":  ["id":1,
                                "questionID":1,
                                "answerContent":"Jajecznicę",
                                "isOpenAnswer":false,
                         "id":2,
                                "questionID":1,
                                "answerContent":"Kiełbaski",
                                "isOpenAnswer":false,
                         "id":3,
                                "questionID":1,
                                "answerContent":"Płatki na mleku",
                                "isOpenAnswer":false,
                         "id":4,
                                "questionID":1,
                                "answerContent":"Inne",
                                "isOpenAnswer":true],
             "id":2,
             "surveyID":1,
             "content":"Czym się zajmujesz w życiu?",
             "tips":"napisz krótką historię",
             "questionType":3,
             "isRequired":true,
             "answers":[]]

但是当我想将 'title' 属性绑定到 &lt;span&gt; &lt;span data-bind="text:title"&gt;&lt;/span&gt; 时,它不起作用。当我在 firefox 中运行我的应用程序并打开 firebug 脚本控制台并将 breakpiont 设置为 line var tmp = @Html.Raw(Model.ToJson()); 返回正确值时,按 F10 转到下一行 var viewModel = ko.mapping.fromJS(tmp); 最后按 F10 并没有任何反应,脚本不执行下一行 ko.applyBindings(viewModel); .

这是我的问题。是否可以使用淘汰映射插件自动映射我的 mvc 模型?或者也许我应该做一些手动工作人员将 mvc 模型映射到淘汰视图模型。

我正在这个网站上寻找答案: link1 和 stackowerflow 但也许我没看懂这篇文章。

编辑

我的观点是这样的:

@using Inżynierka.Extensions
@model Inżynierka.Models.Survey

@
    ViewBag.Title = "Create";



@using (Html.BeginForm())

    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>SurveyAnswer</h4>
        <hr />
        @Html.ValidationSummary(true)

        Title: <span data-bind="text:title"></span>


    </div>



@section Scripts 
        <script src="../../Scripts/jQuery.tmpl.min.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout-3.0.0.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout.validation.js"></script>
        <script src="../../Scripts/knockout.knockout.mapping-latest.js"></script>
        <script type="text/javascript">
            var tmp = @Html.Raw(Model.ToJson());
            var viewModel = ko.mapping.fromJS(tmp);
            ko.applyBindings(viewModel);
        </script>
    @Scripts.Render("~/bundles/jqueryval")

编辑 2

这是我页面的html源代码:

<!DOCTYPE html>
<html>
<head>
    <script type='text/javascript' src='http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js'></script>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Create</title>
    <link href="/Content/bootstrap.css" rel="stylesheet"/>
<link href="/Content/site.css" rel="stylesheet"/>

    <script src="/Scripts/modernizr-2.6.2.js"></script>


</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/">Ankietyy</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="/Surveys">Moje Ankiety</a></li>
                    <li><a href="/">Strona Gł&#243;wna</a></li>
                    <li><a href="/Home/About">O Projekcie</a></li>
                    <li><a href="/Home/Contact">Kontakt</a></li>
                </ul>
                <form action="/Account/LogOff" class="navbar-right" id="logoutForm" method="post"><input name="__RequestVerificationToken" type="hidden" value="fWDZFmyGqJyU3ATUf2IbHDdkbo22bzObUMwUfxfqwXIiqGvRYzMhApWS3I5GkkHnZD7ieDxLfh84s2-prLDtSGeE6_D7p7cT-fmQBszeM06p-fZ7RzhOPn0P8EDftLRwT8YQA8t2U56dlLX_lx3G4Q2" />    <ul class="nav navbar-nav navbar-right">
        <li>
            <a href="/Account/Manage" title="Manage">Witaj Bartek!</a>
        </li>
        <li><a href="javascript:document.getElementById('logoutForm').submit()">Wyloguj się</a></li>
    </ul>
</form>
            </div>
        </div>
    </div>
    <div class="container body-content">




<form action="/SurveyAnswer/CompleteSurvey/1" method="post"><input name="__RequestVerificationToken" type="hidden" value="KOALGZbw0WhFlBV4LHx530Oen59aBWF62b6s58GIUikx3A62uhcAi3-74auJpLtI4fYj9kmcPjlgNu1TeuNrYukpFlll1cGCOIcjjewtFou4M9C3_bHDFk7UoZk_tKpw7SxcXa3UbgwIj4ZhCRM6_g2" />    <div class="form-horizontal">
        <h4>SurveyAnswer</h4>
        <hr />


        Title: <span data-bind="text:title"></span>


    </div>
</form><script type="text/javascript">
            var tmp = "id":1,"surveyCode":null,"title":"Życie","description":"Ankieta, w której zadawane będą pytania na temat codziennego życia ","dateStart":"2013-12-12T00:00:00","dateEnd":"2014-12-30T00:00:00","createDate":"2014-01-07T03:23:16.053","lastModification":"2014-01-07T03:23:16.053","isActive":false,"questions":["id":1,"surveyID":1,"content":"Co jesz na śniadanie?","tips":"wybierz jedną odpowiedź","questionType":1,"isRequired":true,"answers":["id":1,"questionID":1,"answerContent":"Jajecznicę","isOpenAnswer":false,"id":2,"questionID":1,"answerContent":"Kiełbaski","isOpenAnswer":false,"id":3,"questionID":1,"answerContent":"Płatki na mleku","isOpenAnswer":false,"id":4,"questionID":1,"answerContent":"Inne","isOpenAnswer":true],"id":2,"surveyID":1,"content":"Czym się zajmujesz w życiu?","tips":"napisz krótką historię","questionType":3,"isRequired":true,"answers":[],"id":14,"surveyID":1,"content":"Pytanie końcowe","tips":"napisz","questionType":1,"isRequired":true,"answers":["id":9,"questionID":14,"answerContent":"test","isOpenAnswer":false,"id":10,"questionID":14,"answerContent":"test2","isOpenAnswer":false,"id":11,"questionID":14,"answerContent":"test3","isOpenAnswer":false]],"surveyAnswers":[],"codeForUsers":[];
            var viewModel = ko.mapping.fromJS(tmp);
            ko.applyBindings(viewModel);
</script>



        <hr />
        <footer>
            <p>&copy; 2014 - My ASP.NET Application</p>
        </footer>
    </div>

    <script src="/Scripts/jquery-2.0.3.js"></script>

    <script src="/Scripts/bootstrap.js"></script>
<script src="/Scripts/respond.js"></script>


    <script src="../../Scripts/jQuery.tmpl.min.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout-3.0.0.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout.validation.js"></script>
    <script src="../../Scripts/knockout.mapping-latest.js"></script>

    <script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>



<!-- Visual Studio Browser Link -->
<script type="application/json" id="__browserLink_initializationData">
    "appName":"Firefox","requestId":"9f8e517696004299808eb3caccb0e136"
</script>
<script type="text/javascript" src="http://localhost:11897/dc47e85290da49019e6425ddd16f962a/browserLink" async="async"></script>
<!-- End Browser Link -->

</body>
</html>

回答我的问题

视图应该是这样的:

@using Inżynierka.Extensions
@model Inżynierka.Models.Survey

@
    ViewBag.Title = "Create";



@using (Html.BeginForm())

    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>SurveyAnswer</h4>
        <hr />
        @Html.ValidationSummary(true)

        Title: <span data-bind="text:title"></span>


    </div>




@section Scripts 
    <script src="../../Scripts/knockout-3.0.0.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout.mapping-latest.js"></script>
    <script type="text/javascript">
            var tmp = @Html.Raw(Model.ToJson());
            var viewModel = ko.mapping.fromJS(tmp);
            ko.applyBindings(viewModel);
    </script>

    @Scripts.Render("~/bundles/jqueryval")

感谢大家的回复,特别是@VolodymyrBilyachat,他的建议最相关。

【问题讨论】:

您能分享一下您的看法吗? @Volodymyr Bilyachat 我将我的视图添加到帖子中 将模板脚本移动到您的剔除脚本下方,然后将您的视图模型包装在一个 document.ready 函数中 我已经修复了你的视图,现在试试吧 附@VolodymyrBilyachat html源代码 【参考方案1】:

在您发布源代码后,其他想法可能是某些脚本冲突,尝试删除脚本并只留下淘汰赛

【讨论】:

ehhh... 我相信你是对的,但它仍然没有显示我的“标题”。 Mayby 我应该暂时放弃淘汰制映射:P。非常感谢您的回复。 @user3187246 永不放弃让我们修复它,你能渲染页面并发送给我html(查看源代码) 我观察到,当我想在 firebug 脚本控制台中调试它时 var viewModel = ko.mapping.fromJS(tmp); 这会使 firefox 停止工作并且没有回答。 这就是为什么请附上你页面的html源代码。【参考方案2】:

将淘汰视图模型包装在 document.ready 函数中

<script type="text/javascript">
    $document.ready(function() 
            var tmp = @Html.Raw(Model.ToJson());
            var viewModel = ko.mapping.fromJS(tmp);
            ko.applyBindings(viewModel););
    </script>

还请注意,此时您的 viewModel 不是真正的视图模型,因此请考虑使用包含 ko.observable 属性“myData”或其他内容的视图模型来保存您的数据,然后应用绑定

【讨论】:

【参考方案3】:

对于复杂模型,我不相信映射,简单地说,我自己解析 json 并通过循环、ifs 等填充模型。我认为,这不是最糟糕的解决方案,因为调试和修复数据变得更加简单。

【讨论】:

以上是关于从 ASP.NET MVC 复杂模型创建 KnockoutJS 模型的主要内容,如果未能解决你的问题,请参考以下文章

您可以在asp.net mvc中将复杂对象从表单发布到控制器吗

复杂对象和模型绑定器 ASP.NET MVC

ASP.NET MVC 如何从嵌套对象的视图模型集合中动态创建表结构

ASP.Net MVC 模型使用 GET 绑定复杂对象

ASP.net MVC - 如何在各种视图中保留模型

如何在asp.net mvc中返回复杂的Json对象