如何将数据从asp.NET MVC传递到Angular2

时间:2016-04-25 12:44:01

标签: c# asp.net-mvc angular

将数据从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>

亲切的问候,

罗布

7 个答案:

答案 0 :(得分:14)

我发现从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 <input type='hidden'/>元素或隐藏的<code>元素中,使用plain JS来检索值。

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

警告:直接从数据绑定应用程序(如Angular)访问DOM,打破数据绑定模式,应谨慎使用。

答案 1 :(得分:2)

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

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

在Marius Schulz的this post中,您可以看到他序列化数据并使用它来填充模板AngularJS <script> angular.module("hobbitModule").value("companionship", @Html.Raw(Model)); </script> 组件:

window.myNamespace.myServerData

类似的东西可以注入一些数据,例如进入ng-init,然后在其他提供者中使用Angular2引导程序。

在Roel van Lisdonk的this post中,再次使用类似的方法来填充基于AngularJS的模板,使用<div ng-controller="main" ng-init="resources={ textFromResource: '@WebApplication1.Properties.Resources.TextFromResource'}"> <h1>{{ title }}</h1> {{ resources.textFromResource }} </div> 指令:

<asp:ListView ID="ListView1" runat="server">
    <ItemTemplate>
        <asp:Label ID="recipe_name" 
                   runat="Server" 
                   <!-- in eval you use the name of a field/property 
                        found in your collection or datatable    
                   -->
                   Text='<%#Eval("Recipe_Name") %>' />
    </ItemTemplate>
</asp:ListView>

正如第一篇文章指出的那样,需要考虑一下(粘贴在这里):

  

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

     

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

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

HTH

答案 2 :(得分:2)

您可以使用Input公开的@angular/core函数,我有一个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属性。< / p>

答案 3 :(得分:1)

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

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>

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

答案 4 :(得分:1)

<强>的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.component.ts

export class AppComponent {

  private _config : ApplicationConfiguration;

  constructor(config: ApplicationConfiguration) {

    this._config = config;

  }

}

答案 5 :(得分:0)

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

组件HTML:

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

组件TS:

export class MyComponentComponent {
    @Input()
    public CustomAttribute: string;

    constructor() {}

    ngOnInit() {
        console.log("Got it! " + this.CustomAttribute);
    }
}

答案 6 :(得分:0)

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