如何将 asp.net mvc 视图渲染为 angular 2? [英] How to render asp.net mvc view into angular 2?

查看:18
本文介绍了如何将 asp.net mvc 视图渲染为 angular 2?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 asp.net mvc 与 angular 2 应用程序集成.我知道这并不理想,但我被要求将一些现有的 Mvc 功能(想想大型遗留应用程序)集成到一个全新的 Angular 2 spa 中.

我希望能够做的是有一个包含角度组件的 cshtml 视图,以及纯 mvc 的东西...

<action-bar></action-bar>@{Html.RenderPartial("_SuperLegacyPartialView");}

我正在努力寻找任何方法来做到这一点.这篇博文看起来很有希望 - http://www.centare.com/tutorial-angular2-mvc-6-asp-net-5/.它使用了一个指向 Mvc 渲染路径的 templateUrl 值,以及 AsyncRoute,但在 Angular 2 中这些都不再起作用.这篇文章看起来也很有前景 - http://gbataille.github.io/2016/02/16/Angular2-Webpack-AsyncRoute.html,但是它也使用 AsyncRoute,但已弃用.

这在 Angular 1 中曾经非常容易.我们过去要么手动将 angular 引导到 Razor 视图中,要么将部分视图渲染为组件/指令的 templateUrl.在使用 Webpack 的最新 Angular 2 中执行此操作的最佳方法是什么?

解决方案

我想出了一个满足我当时需求的解决方案.我正在将 angular-cli 与 WebPack 一起使用,这满足了我的需求.我不明白我看到的所有使用templateUrl:'/Template/Index'"的示例,其中路径是指向 MVC 视图的路径.这根本行不通,因为在 WebPack 创建的任何捆绑视图中都找不到该路径.也许那些人没有使用 angular-cli 和 WebPack.

这个 stackoverflow 答案 - 如何使用/创建动态模板来使用 Angular 2.0 编译动态组件? 对创建以下指令非常有帮助.该指令将获取 mvc 部分视图的输出并编译它.它允许发生 Razor/服务器逻辑,并且还可以编译一些 angular.虽然,实际上在这个 MVC 部分中包含其他组件是有问题的.如果你成功了,请告诉我你做了什么.就我而言,我只需要进行服务器渲染并将其准确放置在我的 Angular 2 spa 中我想要的位置.

MvcPartialDirective

import {零件,指示,Ng 模块,输入,视图容器引用,编译器,组件工厂,模块与组件工厂,组件引用,反射注入器、OnInit、OnDestroy来自'@angular/core';从 '@angular/router' 导入 { RouterModule };从'@angular/common'导入{CommonModule};从@angular/http"导入{Http};导入 'rxjs/add/operator/map';导出函数 createComponentFactory(compiler: Compiler, metadata: Component): Promise>{const cmpClass = class DynamicComponent {};常量装饰Cmp = 组件(元数据)(cmpClass);@NgModule({ 导入: [CommonModule, RouterModule], 声明: [decoratedCmp] })类 DynamicHtmlModule { }返回 compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule).then((moduleWithComponentFactory: ModuleWithComponentFactories) => {return moduleWithComponentFactory.componentFactories.find(x => x.componentType === modifiedCmp);});}@Directive({ 选择器: 'mvc-partial' })导出类 MvcPartialDirective 实现 OnInit、OnDestroy {html: string = '<p></p>';@Input() 网址:字符串;cmpRef: ComponentRef;构造函数(私有vcRef:ViewContainerRef,私有编译器:编译器,私有http:Http){}ngOnInit() {this.http.get(this.url).map(res => res.text()).订阅((html) =>{this.html = html;如果(!html)返回;如果(this.cmpRef){this.cmpRef.destroy();}const compMetadata = 新组件({选择器:'动态-html',模板:this.html,});createComponentFactory(this.compiler, compMetadata).then(工厂 => {const 注入器 = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);this.cmpRef = this.vcRef.createComponent(工厂, 0, 注入器, []);});},错误 =>控制台日志(错误),() =>console.log('MvcPartial 完成'));}ngOnDestroy() {如果(this.cmpRef){this.cmpRef.destroy();}}}

some-component.html 中(假设您的 mvc 应用与您的 spa 共享域)

<mvc-partial [url]="'/stuffs/mvcstuff'"></mvc-partial>

MvcStuff.cshtml

@{ViewBag.Title = "这是一些 MVC 的东西!!!";}<div><h2>MVC 的东西:</h2><h4>@ViewBag.Title</h4><h2>有角的东西:</h2><h4>{{1 + 1}}</h4>

StuffsController.cs

public PartialViewResult MvcStuff() =>部分视图();

I'm trying to integrate asp.net mvc with an angular 2 application. I understand that this is not ideal, but I am being asked to integrate some existing Mvc functionality (think big legacy app) into a brand new Angular 2 spa.

What I would like to be able to do is have a cshtml view that has angular components in it, as well as pure mvc stuff...

<side-bar></side-bar>
<action-bar></action-bar>

@{
    Html.RenderPartial("_SuperLegacyPartialView");   
}

I'm struggling to find any way to do this. This blog post looked promising - http://www.centare.com/tutorial-angular2-mvc-6-asp-net-5/. It used a templateUrl value that pointed to a path rendered by Mvc, as well as AsyncRoute, but none of that works anymore in Angular 2. This post looked promising as well - http://gbataille.github.io/2016/02/16/Angular2-Webpack-AsyncRoute.html, but it uses AsyncRoute too, which is deprecated.

This used to be very easy in Angular 1. We used to either manually bootstrap angular into a Razor View, or render a partial view as the templateUrl of a component/directive. What is the best way to do this in the latest Angular 2 that uses Webpack?

解决方案

I came up with a solution that satisfied my needs at the time. I'm using angular-cli with WebPack, and this worked for my needs. I don't understand all the examples I've seen that say to use "templateUrl: '/Template/Index'", where the path is a path to an MVC view. That simply doesn't work because the path can't be found inside any of the bundled views that WebPack creates. Maybe those people aren't using angular-cli and WebPack.

This stackoverflow answer - How can I use/create dynamic template to compile dynamic Component with Angular 2.0? was very helpful in creating the following directive. This directive will take the output of an mvc partial view and compile it. It allows for Razor/server logic to take place, and some angular to be compiled as well. Although, actually including other components inside this MVC partial was problematic. If you get that working, please let me know what you did. In my case, I just needed the server rendering to happen and to place that exactly where I wanted it in my Angular 2 spa.

MvcPartialDirective

import {
  Component,
  Directive,
  NgModule,
  Input,
  ViewContainerRef,
  Compiler,
  ComponentFactory,
  ModuleWithComponentFactories,
  ComponentRef,
  ReflectiveInjector, OnInit, OnDestroy
} from '@angular/core';

import { RouterModule }  from '@angular/router';
import { CommonModule } from '@angular/common';
import {Http} from "@angular/http";
import 'rxjs/add/operator/map';

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> {
  const cmpClass = class DynamicComponent {};
  const decoratedCmp = Component(metadata)(cmpClass);

  @NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp] })
  class DynamicHtmlModule { }

  return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
    .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => {
      return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
    });
}

@Directive({ selector: 'mvc-partial' })
export class MvcPartialDirective implements OnInit, OnDestroy {
  html: string = '<p></p>';
  @Input() url: string;
  cmpRef: ComponentRef<any>;

  constructor(private vcRef: ViewContainerRef, private compiler: Compiler, private http: Http) { }

  ngOnInit() {
    this.http.get(this.url)
      .map(res => res.text())
      .subscribe(
        (html) => {
          this.html = html;
          if (!html) return;

          if(this.cmpRef) {
            this.cmpRef.destroy();
          }

          const compMetadata = new Component({
            selector: 'dynamic-html',
            template: this.html,
          });

          createComponentFactory(this.compiler, compMetadata)
            .then(factory => {
              const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
              this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []);
            });
        },
        err => console.log(err),
        () => console.log('MvcPartial complete')
      );

  }

  ngOnDestroy() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
  }
}

in some-component.html (assuming your mvc app shares the domain with your spa)

<mvc-partial [url]="'/stuffs/mvcstuff'"></mvc-partial>

MvcStuff.cshtml

@{
    ViewBag.Title = "This is some MVC stuff!!!";
}
<div>
    <h2>MVC Stuff:</h2>
    <h4>@ViewBag.Title</h4>
    <h2>Angular Stuff:</h2>
    <h4>{{1 + 1}}</h4>
</div>

in StuffsController.cs

public PartialViewResult MvcStuff() => PartialView();

这篇关于如何将 asp.net mvc 视图渲染为 angular 2?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆