【问题标题】:How to pass data from asp.NET MVC to Angular2如何将数据从 asp.NET MVC 传递到 Angular2
【发布时间】:2016-04-25 12:44:00
【问题描述】:

将数据从 ASP.NET MVC 控制器传递到 Angular 2.0 组件的最佳方式是什么?例如,我们使用 ASP.NET MVC 模型并希望将它的 JSON 版本发送到 Angular 以在 Angular 中使用它。

当控制器为视图提供服务时,我们已经可以将一些数据推送到 Angular2(模型)。因此不需要额外的 AJAX 调用来获取该数据。

但是,我正在努力将其“注入”到 Angular 组件中。你怎么做到这一点?这有什么好的参考吗?您可能已经注意到,我对 Angular2 还是很陌生。

我的 index.cshtml 看起来像这样。

<div class="container">
<div>
    <h1>Welcome to the Angular 2 components!</h1>
</div>
<div class="row">
    <MyAngular2Component>
        <div class="alert alert-info" role="alert">
            <h3>Loading...</h3>
        </div>
    </MyAngular2Component>
</div>
</div>

亲切的问候,

罗伯

【问题讨论】:

  • 控制器实际渲染的是什么?我的意思是 Angular2 应用程序由静态文件组成。所以你生成了其中的一些文件?
  • 您需要构建一个提供 JSON 数据的 REST-API。这也许会对您有所帮助:asp.net/web-api/overview/older-versions/…
  • 为了清楚起见:我添加了我正在创建的视图。这是一个 .cshtml 文件。
  • 我通常让我的 mvc 控制器提供混合角色:它们可以提供角度视图(正如您已经拥有的那样),或者它们可以是数据源,而不是返回 html,而是返回 json。可以使用单独的 rest api 以“更清洁”的方式完成,但这种方式有效。
  • @Nathan:你有一个例子如何在 Angular 2 中做到这一点吗?

标签: c# asp.net-mvc angular


【解决方案1】:

我发现从 MVC(或任何托管/启动页面)传入数据的最佳方法是将数据指定为引导组件上的属性,并使用 ElementRef 直接检索值。

下面是从this answer 派生的MVC 示例,它指出不能将@Input 用于根级组件。

示例:

//index.cshtml
<my-app username="@ViewBag.UserName">
    <i class="fa fa-circle-o-notch fa-spin"></i>Loading...
</my-app>


//app.component.ts
import {Component, Input, ElementRef} from '@angular/core';

@Component({
    selector: 'my-app',
    template: '<div> username: <span>{{username}}</span> </div>'
})
export class AppComponent {
    constructor(private elementRef: ElementRef) {}

    username: string = this.elementRef.nativeElement.getAttribute('username')
}

如果要检索不适合某个属性的更复杂的数据,可以使用相同的技术,只需将数据放在 HTML 的&lt;input type='hidden'/&gt; 元素或隐藏的&lt;code&gt; 元素中,然后使用纯 JS 即可检索值。

myJson: string = document.getElementById("myJson").value

警告:直接从 Angular 等数据绑定应用程序访问 DOM,会破坏数据绑定模式,应谨慎使用。

【讨论】:

    【解决方案2】:

    您可能想寻找与 AngularJS 相关的类似问题,而不是特定于 Angular 2,因为事情的主要要点保持不变:

    • 您希望服务器端 Razor 引擎呈现某种视图(即直接 HTML 或 JS)
    • 此视图包含一个 JS 模板,其中部分内容是从服务器模型实例或任何服务器数据(例如资源、字典等)填充的
    • 为了从 Razor 正确填充 JS 变量,C# 服务器端数据必须正确序列化为 JSON 格式

    在 Marius Schulz 的 this post 中,您可以看到他序列化数据并使用它来填充模板 AngularJS value 组件:

    <script>
      angular.module("hobbitModule").value("companionship", @Html.Raw(Model));
    </script>
    

    可以做一些类似的事情来注入一些数据,例如进入 window.myNamespace.myServerData,然后让 Angular2 在其他提供者中引导该值。

    在 Roel van Lisdonk 的 this post 中,再次使用类似的方法来填充基于 AngularJS 的模板,使用 ng-init 指令:

    <div ng-controller="main"
         ng-init="resources={ textFromResource: '@WebApplication1.Properties.Resources.TextFromResource'}">
      <h1>{{ title }}</h1>
      {{ resources.textFromResource }}
    </div>
    

    正如第一篇文章指出的那样,有一些事情需要考虑(粘贴到这里):

    请注意:我即将使用的方法可能不适合处理大量数据。由于 JavaScript 数据内联到 HTML 响应中,因此每次请求该页面时都会通过网络发送。

    此外,如果数据特定于经过身份验证的用户,则无法再缓存响应并将其传递给不同的用户。在考虑以这种方式使用 .NET 数据引导您的 Angular 应用程序时,请记住这一点。

    如果您提供的页面已经是动态的服务器端,即如果它已经从服务器端数据中填充了位,则第二部分可能不是问题。

    HTH

    【讨论】:

      【解决方案3】:

      您需要首先将您的服务和控制器捆绑在单独的模块文件中,并在控制器之前加载服务。 例如:

      dist
      |--services.js
      |--controllers.js
      

      然后你需要通过 ASP.NET MVC JavaScript 结果加载服务的 JavaScript 代码,这里你需要注入你的启动数据。

      public class ScriptController: Controller
      {
        public ActionResult GetServices(){
         string file= File.ReadAllText(Server.MapPath("~dist/services.js"));
         //modify the file to inject data or 
         var result = new JavaScriptResult();         
         result.Script = file;
         return result;     
      }
      

      然后在 index.html 中加载脚本如下

      <script src="/script/getservices"></script>
      <script src="/dist/controller.js"></script>
      

      通过这种方式,您可以在加载时将数据注入到 Angular 代码中。 但是,由于在获取视图、编译视图以及将数据绑定到视图上所花费的时间,即使这样也会对性能产生影响。如果使用服务器端渲染,初始加载性能仍然可以提高。

      【讨论】:

        【解决方案4】:

        您可以使用@angular/core 公开的Input 函数,例如,我有一个Angular 2 组件来向应用程序的用户显示信息消息

        我的 HTML 模板采用 Angular 2 Message 属性

        <div class="alert alert-info col-lg-10 col-lg-offset-1 col-md-10 col-md-offset-1 col-sm-10 col-sm-offset-1 col-xs-10 col-xs-offset-1">
            <i class="fa fa-info-circle"></i> {{ Message }}
        </div>
        

        Message 属性作为输入传递给我的名为 informationmessage.component.ts 的 Angular 2 组件,例如

        import { Component, Input } from '@angular/core';
        
        @Component({
            selector: 'informationmessage',
            templateUrl: '../Templates/informationmessage.component.html'
        })
        export class InformationMessageComponent {
            @Input() Message: string;
        }
        

        然后,例如,我使用 HTML 页面中的属性绑定将数据传递给我的InformationMessageComponent

        <informationmessage [Message]="InformationMessage"></informationmessage>
        

        例如,您可以将上面示例中的 InformationMessage 替换为您从 MVC 控制器获取的数据

        <informationmessage [Message]="@Model.InformationMessage"></informationmessage>
        

        请注意:我没有测试这种情况,但没有技术原因导致它无法正常工作,归根结底,您只是将值绑定到 Angular 2 属性。

        【讨论】:

        • 这不起作用。需要使用@Joseph Gabriel 的解决方案。
        【解决方案5】:

        src/ApplicationConfiguration.ts

        export class ApplicationConfiguration {
            public setting1: string;
            public setting2: string;
        }
        

        src/main.ts

        declare var config : ApplicationConfiguration;
        var providers = [{ provide: ApplicationConfiguration, useValue: config }];
        platformBrowserDynamic(providers).bootstrapModule(AppModule)
        .catch(err => console.log(err));
        

        src/index.html

          <script type="text/javascript">
            var config = {setting1: "value1", setting2: "value2"};
          </script>
        

        src/app/app.component.ts

        export class AppComponent {
        
          private _config : ApplicationConfiguration;
        
          constructor(config: ApplicationConfiguration) {
        
            this._config = config;
        
          }
        
        }
        

        【讨论】:

        • 能否请您添加一些文字您正在做什么以及为什么?最好不要只放代码,还要放解释。
        【解决方案6】:

        我找到了一个更简单的解决方案。不要试图从构造函数中获取属性!请改用ngOnInit() hook。只要该物业已使用@Input() 进行装饰,就可以进入。只是在调用构造函数时它似乎不可用。

        组件 HTML:

        <MyComponent [CustomAttribute]="hello"></MyComponent>
        

        组件 TS:

        export class MyComponentComponent {
            @Input()
            public CustomAttribute: string;
        
            constructor() {}
        
            ngOnInit() {
                console.log("Got it! " + this.CustomAttribute);
            }
        }
        

        【讨论】:

        • 你确定,你的回答证明了这个问题吗?
        【解决方案7】:

        在@Joseph Gabriel 的方法的基础上,如果您希望通过属性 传递复杂对象,则在MVC 中您应该将其序列化为string,然后在角度侧de-使用JSON.Parse对其进行序列化。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-05-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多