mirror of https://github.com/abpframework/abp.git
224 changed files with 1054 additions and 782 deletions
@ -0,0 +1,140 @@ |
|||||
|
# Empezando con ABP y una Aplicacion AspNet Core MVC Web |
||||
|
|
||||
|
Este tutorial explica como empezar una aplicacion ABP desde cero usando las dependencias minimas. Uno generalmente desea |
||||
|
empezar con la **[plantilla de inicio](Getting-Started-AspNetCore-MVC-Template.md)**. |
||||
|
|
||||
|
## Crea un Proyecto Nuevo |
||||
|
|
||||
|
1. Crea una Aplicacion Web AspNet Core nueva usando Visual Studio 2022 (17.0.0+): |
||||
|
|
||||
|
 |
||||
|
|
||||
|
2. Configura el nuevo proyecto: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
3. Presione el boton Create: |
||||
|
|
||||
|
 |
||||
|
|
||||
|
## Instale el paquete Volo.Abp.AspNetCore.Mvc |
||||
|
|
||||
|
Volo.Abp.AspNetCore.Mvc es el paquete de integracion con AspNet Core MVC para ABP. Siendo asi, instalalo en su proyecto: |
||||
|
|
||||
|
```` |
||||
|
Install-Package Volo.Abp.AspNetCore.Mvc |
||||
|
```` |
||||
|
|
||||
|
## Crea el primer modulo ABP |
||||
|
|
||||
|
ABP es un marco de referencia modular y require una clase de **inicio (raíz) tipo modulo** derivada de ``AbpModule``: |
||||
|
|
||||
|
````C# |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.Extensions.Hosting; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace BasicAspNetCoreApplication |
||||
|
{ |
||||
|
[DependsOn(typeof(AbpAspNetCoreMvcModule))] |
||||
|
public class AppModule : AbpModule |
||||
|
{ |
||||
|
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
||||
|
{ |
||||
|
var app = context.GetApplicationBuilder(); |
||||
|
var env = context.GetEnvironment(); |
||||
|
|
||||
|
// Configura la canalización de peticiones HTTP. |
||||
|
if (env.IsDevelopment()) |
||||
|
{ |
||||
|
app.UseExceptionHandler("/Error"); |
||||
|
// El valor por defecto de HSTS es 30 dias. Debes cambiar esto en ambientes productivos. Referencia https://aka.ms/aspnetcore-hsts. |
||||
|
app.UseHsts(); |
||||
|
} |
||||
|
|
||||
|
app.UseHttpsRedirection(); |
||||
|
app.UseStaticFiles(); |
||||
|
app.UseRouting(); |
||||
|
app.UseConfiguredEndpoints(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
``AppModule`` es un buen nombre para el modulo de inicio de una aplicacion. |
||||
|
|
||||
|
Los paquetes de ABP definen clases de tipo modulo y cada modulo puede depender de otro. |
||||
|
En el codigo anterior, el ``AppModule`` depende de el modulo ``AbpAspNetCoreMvcModule`` (definido por el paquete [Volo.Abp.AspNetCore.Mvc](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc)). Es comun agregar el atributo ``DependsOn`` despues de instalar un paquete ABP nuevo. |
||||
|
|
||||
|
En vez de la clase de inicion Startup, estamos configurando una canalizacion de ASP.NET Core en este modulo. |
||||
|
|
||||
|
## La clase Program |
||||
|
|
||||
|
El proximo paso es modificar la clase Program para integrate el sistema de modulos ABP: |
||||
|
|
||||
|
````C# |
||||
|
using BasicAspNetCoreApplication; |
||||
|
|
||||
|
var builder = WebApplication.CreateBuilder(args); |
||||
|
|
||||
|
await builder.Services.AddApplicationAsync<AppModule>(); |
||||
|
|
||||
|
var app = builder.Build(); |
||||
|
|
||||
|
await app.InitializeApplicationAsync(); |
||||
|
await app.RunAsync(); |
||||
|
```` |
||||
|
|
||||
|
``builder.Services.AddApplicationAsync<AppModule>();`` Agrega todos los servicios definidos en todos los modulos empezando desde ``AppModule``. |
||||
|
|
||||
|
``app.InitializeApplicationAsync()`` inicializa y empieza la aplicacion. |
||||
|
|
||||
|
## Ejecutar la Aplicación |
||||
|
|
||||
|
Es todo! Ejecuta la aplicación, debe funcionar como esperado. |
||||
|
|
||||
|
## Uso de Autofac como Marco de Inyección de Dependencia |
||||
|
|
||||
|
Mientras el sistema de Inyección de Dependencia de ASP.NET Core es suficiente para requerimientos basico, [Autofac](https://autofac.org/) proporciona características avanzadas como Inyección de Propiedades e Intercepcion de Metodos, los cuales son necesarios para que ABP pueda llevar a cabo funciones avanzadas. |
||||
|
|
||||
|
El acto de remplazar el sistema DI de ASP.NET Core por Autofac e integrarlo con ABP es facil. |
||||
|
|
||||
|
1. Instala el paquete [Volo.Abp.Autofac](https://www.nuget.org/packages/Volo.Abp.Autofac) |
||||
|
|
||||
|
```` |
||||
|
Install-Package Volo.Abp.Autofac |
||||
|
```` |
||||
|
|
||||
|
2. Agrega la dependencia sobre el modulo ``AbpAutofacModule`` |
||||
|
|
||||
|
````C# |
||||
|
[DependsOn(typeof(AbpAspNetCoreMvcModule))] |
||||
|
[DependsOn(typeof(AbpAutofacModule))] //Agrega la dependencia sobre el modulo ABP Autofac |
||||
|
public class AppModule : AbpModule |
||||
|
{ |
||||
|
... |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
3. Actualiza `Program.cs` para que use Autofac: |
||||
|
|
||||
|
````C# |
||||
|
using BasicAspNetCoreApplication; |
||||
|
|
||||
|
var builder = WebApplication.CreateBuilder(args); |
||||
|
|
||||
|
builder.Host.UseAutofac(); //Agrega esta linea |
||||
|
|
||||
|
await builder.Services.AddApplicationAsync<AppModule>(); |
||||
|
|
||||
|
var app = builder.Build(); |
||||
|
|
||||
|
await app.InitializeApplicationAsync(); |
||||
|
await app.RunAsync(); |
||||
|
```` |
||||
|
|
||||
|
## Codigo fuente |
||||
|
|
||||
|
Obten el codigo fuente del ejemplo creado en este tutorial de [aqui](https://github.com/abpframework/abp-samples/tree/master/BasicAspNetCoreApplication). |
||||
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 178 KiB |
|
After Width: | Height: | Size: 64 KiB |
@ -1,52 +0,0 @@ |
|||||
using System; |
|
||||
using Microsoft.AspNetCore.Http; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.DependencyInjection; |
|
||||
|
|
||||
[ExposeServices( |
|
||||
typeof(IHybridServiceScopeFactory), |
|
||||
typeof(HttpContextServiceScopeFactory) |
|
||||
)] |
|
||||
[Dependency(ReplaceServices = true)] |
|
||||
public class HttpContextServiceScopeFactory : IHybridServiceScopeFactory, ITransientDependency |
|
||||
{ |
|
||||
protected IHttpContextAccessor HttpContextAccessor { get; } |
|
||||
|
|
||||
protected IServiceScopeFactory ServiceScopeFactory { get; } |
|
||||
|
|
||||
public HttpContextServiceScopeFactory( |
|
||||
IHttpContextAccessor httpContextAccessor, |
|
||||
IServiceScopeFactory serviceScopeFactory) |
|
||||
{ |
|
||||
HttpContextAccessor = httpContextAccessor; |
|
||||
ServiceScopeFactory = serviceScopeFactory; |
|
||||
} |
|
||||
|
|
||||
public virtual IServiceScope CreateScope() |
|
||||
{ |
|
||||
var httpContext = HttpContextAccessor.HttpContext; |
|
||||
if (httpContext == null) |
|
||||
{ |
|
||||
return ServiceScopeFactory.CreateScope(); |
|
||||
} |
|
||||
|
|
||||
return new NonDisposedHttpContextServiceScope(httpContext.RequestServices); |
|
||||
} |
|
||||
|
|
||||
protected class NonDisposedHttpContextServiceScope : IServiceScope |
|
||||
{ |
|
||||
public IServiceProvider ServiceProvider { get; } |
|
||||
|
|
||||
public NonDisposedHttpContextServiceScope(IServiceProvider serviceProvider) |
|
||||
{ |
|
||||
ServiceProvider = serviceProvider; |
|
||||
} |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,22 +0,0 @@ |
|||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
[ExposeServices( |
|
||||
typeof(IHybridServiceScopeFactory), |
|
||||
typeof(DefaultServiceScopeFactory) |
|
||||
)] |
|
||||
public class DefaultServiceScopeFactory : IHybridServiceScopeFactory, ITransientDependency |
|
||||
{ |
|
||||
protected IServiceScopeFactory Factory { get; } |
|
||||
|
|
||||
public DefaultServiceScopeFactory(IServiceScopeFactory factory) |
|
||||
{ |
|
||||
Factory = factory; |
|
||||
} |
|
||||
|
|
||||
public IServiceScope CreateScope() |
|
||||
{ |
|
||||
return Factory.CreateScope(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,8 +0,0 @@ |
|||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
public interface IHybridServiceScopeFactory : IServiceScopeFactory |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
@ -1,23 +0,0 @@ |
|||||
using System; |
|
||||
|
|
||||
namespace Volo.Abp.Domain.Entities.Events; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Used to pass data for an event when an entity (<see cref="IEntity"/>) is being changed (creating, updating or deleting).
|
|
||||
/// See <see cref="EntityCreatingEventData{TEntity}"/>, <see cref="EntityDeletingEventData{TEntity}"/> and <see cref="EntityUpdatingEventData{TEntity}"/> classes.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TEntity">Entity type</typeparam>
|
|
||||
[Serializable] |
|
||||
[Obsolete("This event is no longer needed and identical to EntityChangedEventData. Please use EntityChangedEventData instead.")] |
|
||||
public class EntityChangingEventData<TEntity> : EntityEventData<TEntity> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Constructor.
|
|
||||
/// </summary>
|
|
||||
/// <param name="entity">Changing entity in this event</param>
|
|
||||
public EntityChangingEventData(TEntity entity) |
|
||||
: base(entity) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
@ -1,22 +0,0 @@ |
|||||
using System; |
|
||||
|
|
||||
namespace Volo.Abp.Domain.Entities.Events; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// This type of event is used to notify just before creation of an Entity.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TEntity">Entity type</typeparam>
|
|
||||
[Serializable] |
|
||||
[Obsolete("This event is no longer needed and identical to EntityCreatedEventData. Please use EntityCreatedEventData instead.")] |
|
||||
public class EntityCreatingEventData<TEntity> : EntityChangingEventData<TEntity> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Constructor.
|
|
||||
/// </summary>
|
|
||||
/// <param name="entity">The entity which is being created</param>
|
|
||||
public EntityCreatingEventData(TEntity entity) |
|
||||
: base(entity) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
@ -1,22 +0,0 @@ |
|||||
using System; |
|
||||
|
|
||||
namespace Volo.Abp.Domain.Entities.Events; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// This type of event is used to notify just before deletion of an Entity.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TEntity">Entity type</typeparam>
|
|
||||
[Serializable] |
|
||||
[Obsolete("This event is no longer needed and identical to EntityDeletedEventData. Please use EntityDeletedEventData instead.")] |
|
||||
public class EntityDeletingEventData<TEntity> : EntityChangingEventData<TEntity> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Constructor.
|
|
||||
/// </summary>
|
|
||||
/// <param name="entity">The entity which is being deleted</param>
|
|
||||
public EntityDeletingEventData(TEntity entity) |
|
||||
: base(entity) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
@ -1,22 +0,0 @@ |
|||||
using System; |
|
||||
|
|
||||
namespace Volo.Abp.Domain.Entities.Events; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// This type of event is used to notify just before update of an Entity.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TEntity">Entity type</typeparam>
|
|
||||
[Serializable] |
|
||||
[Obsolete("This event is no longer needed and identical to EntityUpdatedEventData. Please use EntityUpdatedEventData instead.")] |
|
||||
public class EntityUpdatingEventData<TEntity> : EntityChangingEventData<TEntity> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Constructor.
|
|
||||
/// </summary>
|
|
||||
/// <param name="entity">The entity which is being updated</param>
|
|
||||
public EntityUpdatingEventData(TEntity entity) |
|
||||
: base(entity) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
@ -1,71 +0,0 @@ |
|||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Shouldly; |
|
||||
using Volo.Abp.Modularity; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
public class HybridServiceScopeFactory_Tests |
|
||||
{ |
|
||||
[Fact] |
|
||||
public async Task Should_Use_Default_ServiceScopeFactory_By_Default_Async() |
|
||||
{ |
|
||||
using (var application = await AbpApplicationFactory.CreateAsync<IndependentEmptyModule>()) |
|
||||
{ |
|
||||
application.Services.AddType(typeof(MyServiceAsync)); |
|
||||
|
|
||||
await application.InitializeAsync(); |
|
||||
|
|
||||
var serviceScopeFactory = application.ServiceProvider.GetRequiredService<IHybridServiceScopeFactory>(); |
|
||||
|
|
||||
using (var scope = serviceScopeFactory.CreateScope()) |
|
||||
{ |
|
||||
scope.ServiceProvider.GetRequiredService<MyServiceAsync>(); |
|
||||
} |
|
||||
|
|
||||
MyServiceAsync.DisposeCount.ShouldBe(1); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_Use_Default_ServiceScopeFactory_By_Default() |
|
||||
{ |
|
||||
using (var application = AbpApplicationFactory.Create<IndependentEmptyModule>()) |
|
||||
{ |
|
||||
application.Services.AddType(typeof(MyService)); |
|
||||
|
|
||||
application.Initialize(); |
|
||||
|
|
||||
var serviceScopeFactory = application.ServiceProvider.GetRequiredService<IHybridServiceScopeFactory>(); |
|
||||
|
|
||||
using (var scope = serviceScopeFactory.CreateScope()) |
|
||||
{ |
|
||||
scope.ServiceProvider.GetRequiredService<MyService>(); |
|
||||
} |
|
||||
|
|
||||
MyService.DisposeCount.ShouldBe(1); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private class MyServiceAsync : ITransientDependency, IDisposable |
|
||||
{ |
|
||||
public static int DisposeCount { get; private set; } |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
++DisposeCount; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private class MyService : ITransientDependency, IDisposable |
|
||||
{ |
|
||||
public static int DisposeCount { get; private set; } |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
++DisposeCount; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,6 +1,6 @@ |
|||||
namespace Volo.Blogging |
namespace Volo.Blogging |
||||
{ |
{ |
||||
public static class BloggingDbProperties |
public static class AbpBloggingDbProperties |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Default value: "Blg".
|
/// Default value: "Blg".
|
||||
@ -0,0 +1,8 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents; |
||||
|
|
||||
|
public class DefaultContentDto : IContent |
||||
|
{ |
||||
|
public List<ContentFragment> ContentFragments { get; set; } |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents; |
||||
|
public interface IContent |
||||
|
{ |
||||
|
public List<ContentFragment> ContentFragments { get; set; } |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents; |
||||
|
|
||||
|
public interface IContentAppService : IApplicationService |
||||
|
{ |
||||
|
Task<List<ContentFragment>> ParseAsync(string content); |
||||
|
} |
||||
@ -1,22 +1,21 @@ |
|||||
using System; |
using System.Collections.Generic; |
||||
using System.Collections.Generic; |
using System; |
||||
using Volo.Abp.Application.Dtos; |
using Volo.Abp.Application.Dtos; |
||||
using Volo.CmsKit.Contents; |
|
||||
|
|
||||
namespace Volo.CmsKit.Public.Pages; |
namespace Volo.CmsKit.Contents; |
||||
|
|
||||
[Serializable] |
[Serializable] |
||||
public class PageDto : EntityDto<Guid> |
public class PageDto : EntityDto<Guid>, IContent |
||||
{ |
{ |
||||
public string Title { get; set; } |
public string Title { get; set; } |
||||
|
|
||||
public string Slug { get; set; } |
public string Slug { get; set; } |
||||
|
|
||||
public string Content { get; set; } |
public string Content { get; set; } |
||||
|
|
||||
public List<ContentFragment> ContentFragments { get; set; } |
public List<ContentFragment> ContentFragments { get; set; } |
||||
|
|
||||
public string Script { get; set; } |
public string Script { get; set; } |
||||
|
|
||||
public string Style { get; set; } |
public string Style { get; set; } |
||||
} |
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.GlobalFeatures; |
||||
|
using Volo.CmsKit.GlobalFeatures; |
||||
|
|
||||
|
namespace Volo.CmsKit.Contents; |
||||
|
|
||||
|
[RequiresGlobalFeature(typeof(PagesFeature))] |
||||
|
public class ContentAppService : CmsKitAppServiceBase, IContentAppService |
||||
|
{ |
||||
|
protected ContentParser ContentParser { get; } |
||||
|
|
||||
|
public ContentAppService(ContentParser contentParser) |
||||
|
{ |
||||
|
ContentParser = contentParser; |
||||
|
} |
||||
|
|
||||
|
public async Task<List<ContentFragment>> ParseAsync(string content) |
||||
|
{ |
||||
|
return await ContentParser.ParseAsync(content); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.CmsKit.Web.Pages.CmsKit.Components.ContentPreview; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Controllers; |
||||
|
|
||||
|
public class CmsKitCommonWidgetsController : AbpController |
||||
|
{ |
||||
|
[HttpPost] |
||||
|
public IActionResult ContentPreview(ContentPreviewDto dto) |
||||
|
{ |
||||
|
return ViewComponent(typeof(ContentPreviewViewComponent), new { content = dto.Content }); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages.CmsKit.Components.ContentPreview; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class ContentPreviewDto |
||||
|
{ |
||||
|
public string Content { get; set; } |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages.CmsKit.Components.ContentPreview; |
||||
|
|
||||
|
public class ContentPreviewViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
protected IContentAppService ContentAppService { get; } |
||||
|
|
||||
|
public ContentPreviewViewComponent(IContentAppService contentAppService) |
||||
|
{ |
||||
|
ContentAppService = contentAppService; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<IViewComponentResult> InvokeAsync(string content) |
||||
|
{ |
||||
|
var fragments = await ContentAppService.ParseAsync(content); |
||||
|
|
||||
|
return View("~/Pages/CmsKit/Components/ContentPreview/Default.cshtml", new DefaultContentDto |
||||
|
{ |
||||
|
ContentFragments = fragments |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
@using Volo.CmsKit.Contents |
||||
|
@using Volo.CmsKit.Web.Pages.CmsKit.Components.Contents |
||||
|
|
||||
|
@model DefaultContentDto |
||||
|
|
||||
|
<div class="content"> |
||||
|
|
||||
|
@await Component.InvokeAsync(typeof(ContentFragmentViewComponent), Model) |
||||
|
|
||||
|
</div> |
||||
@ -0,0 +1,20 @@ |
|||||
|
@using System.Dynamic |
||||
|
@using Volo.Abp.Data |
||||
|
@using Volo.CmsKit.Web.Renderers; |
||||
|
@using Volo.CmsKit.Web.Pages.CmsKit.Components.Contents; |
||||
|
|
||||
|
@model ContentFragmentViewComponent |
||||
|
|
||||
|
@inject IMarkdownToHtmlRenderer MarkdownRenderer |
||||
|
|
||||
|
@foreach (var contentFragment in Model.ContentDto.ContentFragments) |
||||
|
{ |
||||
|
if (contentFragment.Type == "Markdown") |
||||
|
{ |
||||
|
@Html.Raw(await MarkdownRenderer.RenderAsync(contentFragment.GetProperty<string>("Content"))) |
||||
|
} |
||||
|
else if (contentFragment.Type == "Widget") |
||||
|
{ |
||||
|
@await Component.InvokeAsync(contentFragment.GetProperty<string>("Type"), contentFragment.ExtraProperties.ConvertToDynamicObject()) |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
||||
|
using Volo.CmsKit.Contents; |
||||
|
|
||||
|
namespace Volo.CmsKit.Web.Pages.CmsKit.Components.Contents; |
||||
|
|
||||
|
[ViewComponent(Name = "ContentFragment")] |
||||
|
[Widget( |
||||
|
AutoInitialize = true |
||||
|
)] |
||||
|
public class ContentFragmentViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
public IContent ContentDto { get; set; } |
||||
|
|
||||
|
public virtual async Task<IViewComponentResult> InvokeAsync(IContent contentDto) |
||||
|
{ |
||||
|
return View("~/Pages/CmsKit/Components/Contents/ContentFragment.cshtml", new ContentFragmentViewComponent() { ContentDto = contentDto }); |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue