@ -0,0 +1,29 @@ |
|||
<Project> |
|||
<PropertyGroup> |
|||
|
|||
<!-- All Microsoft packages --> |
|||
<MicrosoftPackageVersion>5.0.0</MicrosoftPackageVersion> |
|||
|
|||
<!-- Microsoft.NET.Test.Sdk https://www.nuget.org/packages/Microsoft.NET.Test.Sdk --> |
|||
<MicrosoftNETTestSdkPackageVersion>16.6.1</MicrosoftNETTestSdkPackageVersion> |
|||
|
|||
<!-- NSubstitute https://www.nuget.org/packages/NSubstitute --> |
|||
<NSubstitutePackageVersion>4.2.2</NSubstitutePackageVersion> |
|||
|
|||
<!-- Shouldly https://www.nuget.org/packages/Shouldly --> |
|||
<ShouldlyPackageVersion>3.0.2</ShouldlyPackageVersion> |
|||
|
|||
<!-- xunit https://www.nuget.org/packages/xUnit --> |
|||
<xUnitPackageVersion>2.4.1</xUnitPackageVersion> |
|||
|
|||
<!-- xunit.extensibility.execution https://www.nuget.org/packages/xunit.extensibility.execution --> |
|||
<xUnitExtensibilityExecutionPackageVersion>2.4.1</xUnitExtensibilityExecutionPackageVersion> |
|||
|
|||
<!-- xunit.runner.visualstudio https://www.nuget.org/packages/xunit.runner.visualstudio --> |
|||
<xUnitRunnerVisualstudioPackageVersion>2.4.2</xUnitRunnerVisualstudioPackageVersion> |
|||
|
|||
<!-- Mongo2Go https://www.nuget.org/packages/Mongo2Go --> |
|||
<Mongo2GoPackageVersion>2.2.14</Mongo2GoPackageVersion> |
|||
|
|||
</PropertyGroup> |
|||
</Project> |
|||
@ -0,0 +1,7 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
<packageSources> |
|||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> |
|||
<add key="BlazoriseMyGet" value="https://www.myget.org/F/blazorise/api/v3/index.json" /> |
|||
</packageSources> |
|||
</configuration> |
|||
@ -0,0 +1,14 @@ |
|||
{ |
|||
"culture": "de-DE", |
|||
"texts": { |
|||
"Account": "ABP Benutzerkonto - Anmeldung & Registrierung | ABP.IO", |
|||
"Welcome": "Willkommen", |
|||
"UseOneOfTheFollowingLinksToContinue": "Nutzen Sie einen der nachfolgenden Links um fortzusetzen", |
|||
"FrameworkHomePage": "Framework Website", |
|||
"FrameworkDocumentation": "Framework Dokumentation", |
|||
"OfficialBlog": "Offizieller Blog", |
|||
"CommercialHomePage": "Commercial Website", |
|||
"CommercialSupportWebSite": "Commercial Support-Website", |
|||
"CommunityWebSite": "ABP Community-Website" |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
{ |
|||
"culture": "es", |
|||
"texts": { |
|||
"Account": "Cuenta de ABP - Iniciar sesión y registrarse | ABP.IO", |
|||
"Welcome": "Bienvenido", |
|||
"UseOneOfTheFollowingLinksToContinue": "Usa uno de los siguientes links para continuar", |
|||
"FrameworkHomePage": "Página de inicio del framework", |
|||
"FrameworkDocumentation": "Documentación del framework", |
|||
"OfficialBlog": "Blog Oficial", |
|||
"CommercialHomePage": "Página de inicio comercial", |
|||
"CommercialSupportWebSite": "Sitio web de soporte comercial", |
|||
"CommunityWebSite": "Sitio web comunidad ABP" |
|||
} |
|||
} |
|||
@ -0,0 +1,199 @@ |
|||
{ |
|||
"culture": "de-DE", |
|||
"texts": { |
|||
"Permission:Organizations": "Organisationen", |
|||
"Permission:Manage": "Organisationen verwalten", |
|||
"Permission:DiscountRequests": "Rabattanfragen", |
|||
"Permission:DiscountManage": "Rabattanfragen verwalten", |
|||
"Permission:Disable": "Deaktivieren", |
|||
"Permission:Enable": "Aktivieren", |
|||
"Permission:EnableSendEmail": "E-Mail-Senden aktivieren", |
|||
"Permission:SendEmail": "E-Mail senden", |
|||
"Permission:NpmPackages": "NPM-Pakete", |
|||
"Permission:NugetPackages": "Nuget-Pakete", |
|||
"Permission:Maintenance": "Wartung", |
|||
"Permission:Maintain": "Warten", |
|||
"Permission:ClearCaches": "Caches leeren", |
|||
"Permission:Modules": "Module", |
|||
"Permission:Packages": "Pakete", |
|||
"Permission:Edit": "Bearbeiten", |
|||
"Permission:Delete": "Löschen", |
|||
"Permission:Create": "Erstellen", |
|||
"Permission:Accounting": "Abrechnung", |
|||
"Permission:Accounting:Quotation": "Angebot", |
|||
"Permission:Accounting:Invoice": "Rechnung", |
|||
"Menu:Organizations": "Organisationen", |
|||
"Menu:Accounting": "Abrechnung", |
|||
"Menu:Packages": "Pakete", |
|||
"Menu:DiscountRequests": "Rabattanfragen", |
|||
"NpmPackageDeletionWarningMessage": "Dieses NPM-Paket wird entfernt. Bestätigen Sie das?", |
|||
"NugetPackageDeletionWarningMessage": "Dieses Nuget-Paket wird entfernt. Bestägiten Sie das?", |
|||
"ModuleDeletionWarningMessage": "Dieses Modul wird entfernt. Bestätigen Sie das?", |
|||
"Name": "Name", |
|||
"DisplayName": "Anzeigename", |
|||
"ShortDescription": "Kurzbeschreibung", |
|||
"NameFilter": "Name", |
|||
"CreationTime": "Erstellungszeitpunkt", |
|||
"IsPro": "Ist pro", |
|||
"ShowOnModuleList": "In Modulliste anzeigen", |
|||
"EfCoreConfigureMethodName": "Methodenname konfigurieren", |
|||
"IsProFilter": "Ist pro", |
|||
"ApplicationType": "Anwendungstyp", |
|||
"Target": "Ziel", |
|||
"TargetFilter": "Ziel", |
|||
"ModuleClass": "Modulklasse", |
|||
"NugetPackageTarget.DomainShared": "Gemeinsame Domain", |
|||
"NugetPackageTarget.Domain": "Domain", |
|||
"NugetPackageTarget.Application": "Anwendung", |
|||
"NugetPackageTarget.ApplicationContracts": "Anwedungsverträge", |
|||
"NugetPackageTarget.HttpApi": "HTTP-API", |
|||
"NugetPackageTarget.HttpApiClient": "HTTP-API-Client", |
|||
"NugetPackageTarget.Web": "Web", |
|||
"NugetPackageTarget.EntityFrameworkCore": "DeleteAllEntityFramework Core", |
|||
"NugetPackageTarget.MongoDB": "MongoDB", |
|||
"Edit": "Bearbeiten", |
|||
"Delete": "Löschen", |
|||
"Refresh": "Aktualisieren", |
|||
"NpmPackages": "NPM-Pakete", |
|||
"NugetPackages": "Nuget-Pakete", |
|||
"NpmPackageCount": "NPM-Paketanzahl", |
|||
"NugetPackageCount": "Nuget-Paketanzahl", |
|||
"Module": "Module", |
|||
"ModuleInfo": "Modulinfo", |
|||
"CreateANpmPackage": "Erstellen Sie ein NPM Paket", |
|||
"CreateAModule": "Erstellen Sie in Modul", |
|||
"CreateANugetPackage": "Erstellen Sei ein Nuget-Paket", |
|||
"AddNew": "Neu hinzufügen", |
|||
"PackageAlreadyExist{0}": "\"{0}\" Paket ist bereits hinzugefügt.", |
|||
"ModuleAlreadyExist{0}": "\"{0}\" Modul ist bereits hinzugefügt.", |
|||
"ClearCache": "Cache leeren", |
|||
"SuccessfullyCleared": "Erfolgreich geleert", |
|||
"Menu:NpmPackages": "NPM-Pakete", |
|||
"Menu:Modules": "Module", |
|||
"Menu:Maintenance": "Wartung", |
|||
"Menu:NugetPackages": "Nuget-Pakete", |
|||
"CreateAnOrganization": "Erstellen Sie eine Organisation", |
|||
"Organizations": "Organisationen", |
|||
"LongName": "Lange Name", |
|||
"LicenseType": "Lizenztyp", |
|||
"MissingLicenseTypeField": "Das Feld Lizenztyp ist erforderlich!", |
|||
"LicenseStartTime": "Startzeit der Lizenz", |
|||
"LicenseEndTime": "Endzeit der Lizenz", |
|||
"AllowedDeveloperCount": "Zulässige Entwickleranzahl", |
|||
"UserNameOrEmailAddress": "Benutzername oder E-Mail-Adresse", |
|||
"AddOwner": "Besitzer hinzufügen", |
|||
"UserName": "Benutzername", |
|||
"Email": "E-Mail", |
|||
"Developers": "Entwickler", |
|||
"AddDeveloper": "Entwickler hinzufügen", |
|||
"Create": "Erstellen", |
|||
"UserNotFound": "Benutzer nicht gefunden", |
|||
"{0}WillBeRemovedFromDevelopers": "{0} wird von den Entwicklern entfernt. Bestätigen Sie das?", |
|||
"{0}WillBeRemovedFromOwners": "{0} wird von den Besitzern entfernt. Bestätigen Sie das?", |
|||
"Computers": "Computer", |
|||
"UniqueComputerId": "Eindeutig Computer-ID", |
|||
"LastSeenDate": "Zuletzt gesehenes Datum", |
|||
"{0}Computer{1}WillBeRemovedFromRecords": "Computer von {0} ({1}) wird aus den Datensätzen entfernt", |
|||
"OrganizationDeletionWarningMessage": "Organisation wird gelöscht", |
|||
"DeletingLastOwnerWarningMessage": "Eine Organisation muss zumindest einen Besitzer aufweisen! Daher können Sie diesen Besitzer nicht entfernen", |
|||
"This{0}AlreadyExistInThisOrganization": "Dies {0} existiert bereits in dieser Organisation", |
|||
"AreYouSureYouWantToDeleteAllComputers": "Sind Sie sicher, dass Sie alle Computer löschen möchten?", |
|||
"DeleteAll": "Alles Löschen", |
|||
"DoYouWantToCreateNewUser": "Möchten Sie einen neuen Benutzer erstellen?", |
|||
"MasterModules": "Master-Module", |
|||
"OrganizationName": "Organisationsname", |
|||
"CreationDate": "Erstellungsdatum", |
|||
"LicenseStartDate": "Startdatum der Lizenz", |
|||
"LicenseEndDate": "Enddatum der Lizenz", |
|||
"OrganizationNamePlaceholder": "Organisationsname...", |
|||
"TotalQuestionCountPlaceholder": "Gesamtzahl der Fragen...", |
|||
"RemainingQuestionCountPlaceholder": "Anzahl verbleibender Fragen...", |
|||
"LicenseTypePlaceholder": "Lizenztyp...", |
|||
"CreationDatePlaceholder": "Erstellungsdatum...", |
|||
"LicenseStartDatePlaceholder": "Startdatum der Lizenz...", |
|||
"LicenseEndDatePlaceholder": "Enddatum der Lizenz...", |
|||
"UsernameOrEmail": "Benutzername oder E-Mail-Adresse", |
|||
"UsernameOrEmailPlaceholder": "Benutzername oder E-Mail-Adresse...", |
|||
"Member": "Mitglied", |
|||
"PurchaseOrderNo": "Bestellnummer", |
|||
"QuotationDate": "Angebotsdatum", |
|||
"CompanyName": "Firmenname", |
|||
"CompanyAddress": "Firmenanschrift", |
|||
"Price": "Preis", |
|||
"DiscountText": "Rabatttext", |
|||
"DiscountQuantity": "Rabattmenge", |
|||
"DiscountPrice": "Rabattpreis", |
|||
"Quotation": "Angebot", |
|||
"ExtraText": "Zusätzlicher Text", |
|||
"ExtraAmount": "Zusätzliche Menge", |
|||
"DownloadQuotation": "Angebot herunterladen", |
|||
"Invoice": "Rechnung", |
|||
"TaxNumber": "Steuernummer", |
|||
"InvoiceNumber": "Rechnungsnummer", |
|||
"InvoiceDate": "Rechnungsdatum", |
|||
"InvoiceNote": "Rechnungsnotiz", |
|||
"Quantity": "Menge", |
|||
"AddProduct": "Produkt hinzufügen", |
|||
"AddProductWarning": "Sie müssen ein Produkt hinzufügen!", |
|||
"TotalPrice": "Gesamtpreis", |
|||
"Generate": "Generieren", |
|||
"MissingQuantityField": "Das Feld Menge ist erforderlich!", |
|||
"MissingPriceField": "Das Feld Preis ist erforderlich!", |
|||
"CodeUsageStatus": "Status", |
|||
"Country": "Land", |
|||
"DeveloperCount": "Entwickleranzahl", |
|||
"RequestCode": "Anfrage-Code", |
|||
"WebSite": "Webseite", |
|||
"GithubUsername": "Github Benutzername", |
|||
"PhoneNumber": "Telefonnummer", |
|||
"ProjectDescription": "Projektbeschreibung", |
|||
"Referrer": "Referrer", |
|||
"DiscountRequests": "Rabattanfrage", |
|||
"Copylink": "Link kopieren", |
|||
"Disable": "Deaktivieren", |
|||
"Enable": "Aktivieren", |
|||
"EnableSendEmail": "E-Mail-Senden aktivieren", |
|||
"SendEmail": "E-Mail senden", |
|||
"SuccessfullyDisabled": "Erfolgreich deaktiviert", |
|||
"SuccessfullyEnabled": "Erfolgreich aktiviert", |
|||
"EmailSent": "E-Mail gesendet", |
|||
"SuccessfullySent": "Erfolgreich gesendet", |
|||
"SuccessfullyDeleted": "Erfolgreich gelöscht", |
|||
"DiscountRequestDeletionWarningMessage": "Rabattanfrage wird gelöscht", |
|||
"BusinessType": "Unternehmensart", |
|||
"TotalQuestionCount": "Gesamtzahl der Fragen", |
|||
"RemainingQuestionCount": "Anzahl verbleibender Fragen", |
|||
"TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount muss größer sein als RemainingQuestionCount !", |
|||
"QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount und RemainingQuestionCount müssen Null oder größer als Null sein !", |
|||
"UnlimitedQuestionCount": "Unbegrenzte Anzahl von Fragen", |
|||
"Notes": "Anmerkungen", |
|||
"Menu:Community": "Community", |
|||
"Menu:Articles": "Beiträge", |
|||
"Wait": "Warten", |
|||
"Approve": "Genehmigen", |
|||
"Reject": "Ablehnen", |
|||
"Details": "Details", |
|||
"Url": "URL", |
|||
"Title": "Titel", |
|||
"ContentSource": "Inhaltsquelle", |
|||
"Status": "Status", |
|||
"ReadArticle": "Beitrag lesen", |
|||
"ArticleHasBeenWaiting": "Beitrag hat gewartet", |
|||
"ArticleHasBeenApproved": "Beitrag wurde genehmigt", |
|||
"ArticleHasBeenRejected": "Beitrag wurde abgelehnt", |
|||
"Permission:Community": "Community", |
|||
"Permission:CommunityArticle": "Beitrag", |
|||
"Link": "Link", |
|||
"Enum:ContentSource:0": "Github", |
|||
"Enum:ContentSource:1": "Extern", |
|||
"Enum:Status:0": "Wartend", |
|||
"Enum:Status:1": "Abgelehnt", |
|||
"Enum:Status:2": "Genehmigt", |
|||
"Summary": "Zusammenfassung", |
|||
"AuthorName": "Autorenname", |
|||
"CoverImage": "Titelbild", |
|||
"RemoveCacheConfirmationMessage": "Sind Sie sicher, dass Sie den Cache für den Artikel \"{0}\" entfernen wollen?", |
|||
"SuccessfullyRemoved": "Erfolgreich geleert", |
|||
"RemoveCache": "Cache entfernen" |
|||
} |
|||
} |
|||
@ -0,0 +1,199 @@ |
|||
{ |
|||
"culture": "es", |
|||
"texts": { |
|||
"Permission:Organizations": "Organizaciones", |
|||
"Permission:Manage": "Gestionar organizaciones", |
|||
"Permission:DiscountRequests": "Solicitudes de descuento", |
|||
"Permission:DiscountManage": "Gestionar solicitudes de descuento", |
|||
"Permission:Disable": "Desactivar", |
|||
"Permission:Enable": "Activar", |
|||
"Permission:EnableSendEmail": "Activar enviar email", |
|||
"Permission:SendEmail": "Enviar email", |
|||
"Permission:NpmPackages": "Paquetes NPM", |
|||
"Permission:NugetPackages": "Paquetes Nuget", |
|||
"Permission:Maintenance": "Mantenimiento", |
|||
"Permission:Maintain": "Mantener", |
|||
"Permission:ClearCaches": "Borrar cachés", |
|||
"Permission:Modules": "Módulos", |
|||
"Permission:Packages": "Paquetes", |
|||
"Permission:Edit": "Editar", |
|||
"Permission:Delete": "Borrar", |
|||
"Permission:Create": "Crear", |
|||
"Permission:Accounting": "Contabilidad", |
|||
"Permission:Accounting:Quotation": "Cotización", |
|||
"Permission:Accounting:Invoice": "Factura", |
|||
"Menu:Organizations": "Organizaciones", |
|||
"Menu:Accounting": "Contabilidad", |
|||
"Menu:Packages": "Paquetes", |
|||
"Menu:DiscountRequests": "Solicitudes de descuento", |
|||
"NpmPackageDeletionWarningMessage": "Este NPM paquete será borrado. ¿Quieres confirmar?", |
|||
"NugetPackageDeletionWarningMessage": "Este NPM paquete será borrado. ¿Quieres confirmar?", |
|||
"ModuleDeletionWarningMessage": "Este NPM paquete será borrado. ¿Quieres confirmar?", |
|||
"Name": "Nombre", |
|||
"DisplayName": "Nombre para mostrar", |
|||
"ShortDescription": "Descripción corta", |
|||
"NameFilter": "Nombre", |
|||
"CreationTime": "Fecha de creación", |
|||
"IsPro": "Es pro", |
|||
"ShowOnModuleList": "Mostrar en la lista de módulos", |
|||
"EfCoreConfigureMethodName": "configurar nombre de método", |
|||
"IsProFilter": "Es pro", |
|||
"ApplicationType": "tipo de aplicación", |
|||
"Target": "Destino", |
|||
"TargetFilter": "Destino", |
|||
"ModuleClass": "Módulo de clase", |
|||
"NugetPackageTarget.DomainShared": "Dominio compartido", |
|||
"NugetPackageTarget.Domain": "Dominio", |
|||
"NugetPackageTarget.Application": "Aplicación", |
|||
"NugetPackageTarget.ApplicationContracts": "Contratos de aplicación", |
|||
"NugetPackageTarget.HttpApi": "Http Api", |
|||
"NugetPackageTarget.HttpApiClient": "Cliente Http Api", |
|||
"NugetPackageTarget.Web": "Web", |
|||
"NugetPackageTarget.EntityFrameworkCore": "Delete todo EntityFramework Core", |
|||
"NugetPackageTarget.MongoDB": "MongoDB", |
|||
"Edit": "Editar", |
|||
"Delete": "Borrar", |
|||
"Refresh": "Refrescar", |
|||
"NpmPackages": "Paquetes NPM", |
|||
"NugetPackages": "Paquetes Nuget", |
|||
"NpmPackageCount": "Número de paquetes NPM", |
|||
"NugetPackageCount": "Número de paquetes Nuget", |
|||
"Module": "Módulos", |
|||
"ModuleInfo": "Info de módulo", |
|||
"CreateANpmPackage": "Crear un paquete NPM", |
|||
"CreateAModule": "Crear un módulo", |
|||
"CreateANugetPackage": "Crear un paquete de Nuget", |
|||
"AddNew": "Añadir nuevo", |
|||
"PackageAlreadyExist{0}": "\"{0}\" paquete ya se encuentra añadido", |
|||
"ModuleAlreadyExist{0}": "\"{0}\" módulo ya se encuentra añadido.", |
|||
"ClearCache": "Borrar caché", |
|||
"SuccessfullyCleared": "Borrado satisfactoriamente", |
|||
"Menu:NpmPackages": "Paquetes de NPM", |
|||
"Menu:Modules": "Módulos", |
|||
"Menu:Maintenance": "Mantenimiento", |
|||
"Menu:NugetPackages": "Paquetes Nuget", |
|||
"CreateAnOrganization": "Crear una organización", |
|||
"Organizations": "Organizaciones", |
|||
"LongName": "Nombre largo", |
|||
"LicenseType": "Tipo de licencia", |
|||
"MissingLicenseTypeField": "El campo tipo de licencia es requerido!", |
|||
"LicenseStartTime": "Fecha de inicio de licencia", |
|||
"LicenseEndTime": "Fecha de caducidad de licencia", |
|||
"AllowedDeveloperCount": "Número de desarrolladores permitidos", |
|||
"UserNameOrEmailAddress": "Nombre de usuario o", |
|||
"AddOwner": "Añadir propietario", |
|||
"UserName": "Nombre de usuario", |
|||
"Email": "Email", |
|||
"Developers": "Desarrolladores", |
|||
"AddDeveloper": "Añadir desarrollador", |
|||
"Create": "Crear", |
|||
"UserNotFound": "Usuario no encontrado", |
|||
"{0}WillBeRemovedFromDevelopers": "{0} será eliminado de desarrolladores, ¿deseas continuar?", |
|||
"{0}WillBeRemovedFromOwners": "{0} será eliminado de propietarios, ¿deseas continuar?", |
|||
"Computers": "Ordenadores", |
|||
"UniqueComputerId": "Id única de ordenador", |
|||
"LastSeenDate": "Fecha de visto por última vez", |
|||
"{0}Computer{1}WillBeRemovedFromRecords": "El ordenador {0} ({1}) será eliminado de los registros", |
|||
"OrganizationDeletionWarningMessage": "La organización será eliminada", |
|||
"DeletingLastOwnerWarningMessage": "Una organización debe tener al menos un propietario!. Por lo tanto, tu no puedes eliminar este propietario", |
|||
"This{0}AlreadyExistInThisOrganization": "Este/a {0} ya existe en esta organización", |
|||
"AreYouSureYouWantToDeleteAllComputers": "Estás seguro tu quieres eliminar todos los ordenadores", |
|||
"DeleteAll": "Eliminar todo", |
|||
"DoYouWantToCreateNewUser": "¿Quieres crear un nuevo usuario?", |
|||
"MasterModules": "Módulos maestros", |
|||
"OrganizationName": "Nombre de organización", |
|||
"CreationDate": "Fecha de creación", |
|||
"LicenseStartDate": "Fecha de inicio de licencia", |
|||
"LicenseEndDate": "Fecha de caducidad de licencia", |
|||
"OrganizationNamePlaceholder": "Nombre de organización...", |
|||
"TotalQuestionCountPlaceholder": "Número total de preguntas...", |
|||
"RemainingQuestionCountPlaceholder": "Número de preguntas pendientes", |
|||
"LicenseTypePlaceholder": "Tipo de licencia...", |
|||
"CreationDatePlaceholder": "Fecha de creación...", |
|||
"LicenseStartDatePlaceholder": "Fecha de inicio de licencia...", |
|||
"LicenseEndDatePlaceholder": "Fecha de caducidad de licencia...", |
|||
"UsernameOrEmail": "Usuario o email", |
|||
"UsernameOrEmailPlaceholder": "Usuario o email...", |
|||
"Member": "Miembro", |
|||
"PurchaseOrderNo": "Número de orden de compra", |
|||
"QuotationDate": "Fecha de presupuesto", |
|||
"CompanyName": "Nombre de empresa", |
|||
"CompanyAddress": "Dirección de empresa", |
|||
"Price": "Precio", |
|||
"DiscountText": "Texto de descuento", |
|||
"DiscountQuantity": "Cantidad de descuento", |
|||
"DiscountPrice": "Precio de descuento", |
|||
"Quotation": "Presupuesto", |
|||
"ExtraText": "Texto extra", |
|||
"ExtraAmount": "Cantidad extra", |
|||
"DownloadQuotation": "Descarga el presupuesto", |
|||
"Invoice": "Factura", |
|||
"TaxNumber": "Identificación fiscal", |
|||
"InvoiceNumber": "Número de factura", |
|||
"InvoiceDate": "Fecha de factura", |
|||
"InvoiceNote": "Nota de factura", |
|||
"Quantity": "Cantidad", |
|||
"AddProduct": "Añadir producto", |
|||
"AddProductWarning": "Tu necesitas añadir un producto!", |
|||
"TotalPrice": "Precio total", |
|||
"Generate": "Generar", |
|||
"MissingQuantityField": "El campo cantidad es requerido!", |
|||
"MissingPriceField": "El campo precio es requerido!", |
|||
"CodeUsageStatus": "Estado", |
|||
"Country": "País", |
|||
"DeveloperCount": "Cuentas de desarrollo", |
|||
"RequestCode": "Solicitud de código", |
|||
"WebSite": "Sitio web", |
|||
"GithubUsername": "Nombre de usuario Github", |
|||
"PhoneNumber": "Número de teléfono", |
|||
"ProjectDescription": "Descripción del proyecto", |
|||
"Referrer": "Referente", |
|||
"DiscountRequests": "Solicitud de descuento", |
|||
"Copylink": "Copiar Link", |
|||
"Disable": "Deshabilitar", |
|||
"Enable": "Habilitar", |
|||
"EnableSendEmail": "Habilitar el envío de Email", |
|||
"SendEmail": "Enviar Email", |
|||
"SuccessfullyDisabled": "Deshabilitado correctamente", |
|||
"SuccessfullyEnabled": "Habilitado correctamente", |
|||
"EmailSent": "Email enviado", |
|||
"SuccessfullySent": "Enviado correctamente", |
|||
"SuccessfullyDeleted": "Borrado correctamente", |
|||
"DiscountRequestDeletionWarningMessage": "La solicitud de descuento será borrada", |
|||
"BusinessType": "Tipo de negocio", |
|||
"TotalQuestionCount": "Número total de preguntas", |
|||
"RemainingQuestionCount": "Número de preguntas restantes", |
|||
"TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount debe ser mayor que RemainingQuestionCount !", |
|||
"QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount y RemainingQuestionCount debe ser cero o más grande que cero !", |
|||
"UnlimitedQuestionCount": "Número de preguntas ilimitadas", |
|||
"Notes": "Notas", |
|||
"Menu:Community": "Comunidad", |
|||
"Menu:Articles": "Artículos", |
|||
"Wait": "Esperar", |
|||
"Approve": "Aprobar", |
|||
"Reject": "Rechazar", |
|||
"Details": "Detalles", |
|||
"Url": "Url", |
|||
"Title": "Título", |
|||
"ContentSource": "Fuente de contenido", |
|||
"Status": "Estado", |
|||
"ReadArticle": "Leer artículo", |
|||
"ArticleHasBeenWaiting": "El artículo ha sido puesto en espera", |
|||
"ArticleHasBeenApproved": "El artículo ha sido aprobado", |
|||
"ArticleHasBeenRejected": "El artículo ha sido rechazado", |
|||
"Permission:Community": "Comunidad", |
|||
"Permission:CommunityArticle": "Artículo", |
|||
"Link": "Link", |
|||
"Enum:ContentSource:0": "Github", |
|||
"Enum:ContentSource:1": "Externo", |
|||
"Enum:Status:0": "En espera", |
|||
"Enum:Status:1": "Rechazado", |
|||
"Enum:Status:2": "Aprobado", |
|||
"Summary": "Resumen", |
|||
"AuthorName": "Nombre del autor", |
|||
"CoverImage": "Imagen de portada", |
|||
"RemoveCacheConfirmationMessage": "¿Estás seguro que quieres borrar la caché para \"{0}\" artículo?", |
|||
"SuccessfullyRemoved": "Borrada correctamente", |
|||
"RemoveCache": "" |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
{ |
|||
"culture": "de-DE", |
|||
"texts": { |
|||
"Volo.AbpIo.Domain:010004": "Maximale Mitgliederanzahl erreicht!", |
|||
"Volo.AbpIo.Domain:010005": "Miximale Besizeranzahl erreicht!", |
|||
"Volo.AbpIo.Domain:010006": "Dieser Benutzer ist bereits ein Besitzer in dieser Organisation!", |
|||
"Volo.AbpIo.Domain:010007": "Dieser Benutzer ist bereits ein Entwickler in dieser Organisation!", |
|||
"Volo.AbpIo.Domain:010008": "Die zulässige Entwickleranzahl darf nicht geringer sein als die aktuelle Entwickleranzahl!", |
|||
"Volo.AbpIo.Domain:010009": "Die zulässige Entwickleranzahl darf nicht kleiner als 0 sein!", |
|||
"Volo.AbpIo.Domain:010010": "Die maximale Anzahl der Mac-Adressen ist überschritten!", |
|||
"Volo.AbpIo.Domain:010011": "Die persönliche Lizenz kann nicht mehr als 1 Entwickler haben!", |
|||
"Volo.AbpIo.Domain:010012": "Die Lizenz kann nicht einen Monat nach Ablauf der Lizenz verlängert werden!", |
|||
"Volo.AbpIo.Domain:020001": "Dieses NPM-Paket konnte nicht gelöscht werden, da \"{NugetPackages}\" Nuget-Pakete von diesem Paket abhängig sind.", |
|||
"Volo.AbpIo.Domain:020002": "Dieses NPM-Paket konnte nicht gelöscht werden, da \"{Module}\" Module dieses Paket verwenden.", |
|||
"Volo.AbpIo.Domain:020003": "Dieses NPM-Paket konnte nicht gelöscht werden, da \"{Module}\" Module dieses Paket verwenden und \"{NugetPackages}\" Nuget-Pakete von diesem Paket abhängig sind.", |
|||
"Volo.AbpIo.Domain:020004": "Dieses Nuget-Paket konnte nicht gelöscht werden, da \"{Module}\" Module dieses Paket verwenden.", |
|||
"WantToLearn?": "Wollen Sie sich einlernen?", |
|||
"ReadyToGetStarted?": "Bereit anzufangen?", |
|||
"JoinOurCommunity": "Tritt unserer Community bei", |
|||
"GetStartedUpper": "LOSLEGEN", |
|||
"ForkMeOnGitHub": "Fork me on GitHub", |
|||
"Features": "Features", |
|||
"GetStarted": "Loslegen", |
|||
"Documents": "Unterlagen", |
|||
"Community": "Community", |
|||
"ContributionGuide": "Leitfaden für Mitwirkende", |
|||
"Blog": "Blog", |
|||
"Commercial": "Commercial", |
|||
"MyAccount": "Mein Benutzerkonto", |
|||
"SeeDocuments": "Siehe Unterlagen", |
|||
"Samples": "Beispiele" |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
{ |
|||
"culture": "es", |
|||
"texts": { |
|||
"Volo.AbpIo.Domain:010004": "Número máximo de miembros alcanzado!", |
|||
"Volo.AbpIo.Domain:010005": "Número máximo de propietarios alcanzado!", |
|||
"Volo.AbpIo.Domain:010006": "Este usuario ya es un propietario de esta organización!", |
|||
"Volo.AbpIo.Domain:010007": "Este usuario ya es un desarrollador en este organización!", |
|||
"Volo.AbpIo.Domain:010008": "Número de desarrolladores permitido no puede ser menor que el número actual de desarrolladores!", |
|||
"Volo.AbpIo.Domain:010009": "El número de desarrolladores no puede ser menor que cero!", |
|||
"Volo.AbpIo.Domain:010010": "Número máximo de dirección mac excedido!", |
|||
"Volo.AbpIo.Domain:010011": "Una licencia personal no puede tener más de un desarrollador!", |
|||
"Volo.AbpIo.Domain:010012": "La licencia no puede ser extendida un mes despues de que expire!", |
|||
"Volo.AbpIo.Domain:020001": "Este paquete NPM no pudo ser borrado porque \"{NugetPackages}\" paquetes Nuget son dependientes de este paquete.", |
|||
"Volo.AbpIo.Domain:020002": "Este paquete NPM no pudo ser borrado porque \"{Modules}\" modulos están usando este paquete.", |
|||
"Volo.AbpIo.Domain:020003": "Este paquete NPM no pudo ser borrado porque \"{Modules}\" modulos están usando este paquete.y \"{NugetPackages}\" paquetes Nuget son dependientes de este paquete.", |
|||
"Volo.AbpIo.Domain:020004": "Este paquete Nuget no pudo ser borrado porque \"{Modules}\" modulos están usando este paquete.", |
|||
"WantToLearn?": "¿Quieres aprender?", |
|||
"ReadyToGetStarted?": "¿Preparado para comenzar?", |
|||
"JoinOurCommunity": "Unete a nuestra comunidad", |
|||
"GetStartedUpper": "COMENZAR", |
|||
"ForkMeOnGitHub": "Fork en GitHub", |
|||
"Features": "Características", |
|||
"GetStarted": "Comenzar", |
|||
"Documents": "Documentos", |
|||
"Community": "Comunidad", |
|||
"ContributionGuide": "Guia de contribución", |
|||
"Blog": "Blog", |
|||
"Commercial": "Comercial", |
|||
"MyAccount": "Mi cuenta", |
|||
"SeeDocuments": "Ver documentos", |
|||
"Samples": "Ejemplos" |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
{ |
|||
"culture": "de-DE", |
|||
"texts": { |
|||
"OrganizationManagement": "Organisationsverwaltung", |
|||
"OrganizationList": "Organisationsauflistung", |
|||
"Volo.AbpIo.Commercial:010003": "Sie sind der Besitzer dieser Organisation!", |
|||
"OrganizationNotFoundMessage": "Keine Organisation gefunden!", |
|||
"DeveloperCount": "Zugeordnete / Gesamte Entwickler", |
|||
"QuestionCount": "Verbleibende / Gesamte Fragen", |
|||
"Unlimited": "Unbegrenzt", |
|||
"Owners": "Besitzer", |
|||
"AddMember": "Mitglied hinzufügen", |
|||
"AddOwner": "Besizer hinzufügen", |
|||
"AddDeveloper": "Entwickler hinzufügen", |
|||
"UserName": "Benutzername", |
|||
"Name": "Name", |
|||
"EmailAddress": "E-Mail-Adress", |
|||
"Developers": "Entwickler", |
|||
"LicenseType": "Lizenztyp", |
|||
"Manage": "Verwalten", |
|||
"StartDate": "Startdatum", |
|||
"EndDate": "Enddatum", |
|||
"Modules": "Module", |
|||
"LicenseExtendMessage": "Ihr Lizenzenddatum wird auf {0} verlängert", |
|||
"LicenseUpgradeMessage": "Ihre Lizenz wird auf {0} aktualisiert", |
|||
"LicenseAddDeveloperMessage": "{0} Entwickler zu Ihrer Lizenz hinzugefügt", |
|||
"Volo.AbpIo.Commercial:010004": "Kann den angegebenen Benutzer nicht finden! Der Benutzer muss sich bereits registriert haben.", |
|||
"MyOrganizations": "Meine Organisationen", |
|||
"ApiKey": "API-Schlüssel", |
|||
"UserNameNotFound": "Es gibt keinen Benutzer mit dem Benutzernamen {0}", |
|||
"SuccessfullyAddedToNewsletter": "Vielen Dank, dass Sie unseren Newsletter abonniert haben!", |
|||
"MyProfile": "Mein Profil", |
|||
"EmailNotValid": "Bitte geben Sie eine gültige E-Mail-Adresse ein." |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
{ |
|||
"culture": "es", |
|||
"texts": { |
|||
"OrganizationManagement": "Gestión de la organización", |
|||
"OrganizationList": "Lista organización", |
|||
"Volo.AbpIo.Commercial:010003": "Tu no eres el propietario de esta organización!", |
|||
"OrganizationNotFoundMessage": "Organización no encontrada!", |
|||
"DeveloperCount": "Total desarrolladores asignados", |
|||
"QuestionCount": "Total de preguntas restantes", |
|||
"Unlimited": "Ilimitado", |
|||
"Owners": "Propietarios", |
|||
"AddMember": "Añadir miembro", |
|||
"AddOwner": "Añadir propietario", |
|||
"AddDeveloper": "Añadir desarrollador", |
|||
"UserName": "Nombre de usuario", |
|||
"Name": "Nombre", |
|||
"EmailAddress": "Dirección de Email", |
|||
"Developers": "Desarrolladores", |
|||
"LicenseType": "Tipo de licencia", |
|||
"Manage": "Gestionar", |
|||
"StartDate": "Fecha de inicio", |
|||
"EndDate": "Fecha de fin", |
|||
"Modules": "Módulos", |
|||
"LicenseExtendMessage": "Tu fecha de finalización de tu licencia ha sido extendido a {0}", |
|||
"LicenseUpgradeMessage": "Tu licencia esta actualizada a {0}", |
|||
"LicenseAddDeveloperMessage": "{0} desarrolladores añadidos a tu licencia", |
|||
"Volo.AbpIo.Commercial:010004": "No se pudo encontrar el usuario especificado. El usuario debe estar ya registrado.", |
|||
"MyOrganizations": "Mis organizaciones", |
|||
"ApiKey": "API Key", |
|||
"UserNameNotFound": "No hay un usuario con el nombre de usuario {0}", |
|||
"SuccessfullyAddedToNewsletter": "Gracias por suscribirte a nuestro boletín de noticias!", |
|||
"MyProfile": "Mi perfil", |
|||
"EmailNotValid": "Por favor, introduce una dirección de email válida." |
|||
} |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
{ |
|||
"culture": "de-DE", |
|||
"texts": { |
|||
"Permission:CommunityArticle": "Community-Beitrag", |
|||
"Permission:Edit": "Bearbeiten", |
|||
"Waiting": "Wartend", |
|||
"Approved": "Genehmigt", |
|||
"Rejected": "Abgelehnt", |
|||
"Wait": "Warten", |
|||
"Approve": "Genehmigen", |
|||
"Reject": "Ablehnen", |
|||
"ReadArticle": "Beitrag lesen", |
|||
"Status": "Status", |
|||
"ContentSource": "Inhaltsquelle", |
|||
"Details": "Details", |
|||
"Url": "URL", |
|||
"Title": "Titel", |
|||
"CreationTime": "Erstellungszeitpunkt", |
|||
"Save": "Speichern", |
|||
"SameUrlAlreadyExist": "Dieselbe URL existiert bereits, wenn Sie diesen Beitrag hinzufügen möchten, sollten Sie die URL ändern!", |
|||
"UrlIsNotValid": "Der URL ist nicht korrekt.", |
|||
"UrlNotFound": "URL nicht gefunden.", |
|||
"UrlContentNotFound": "URL-Inhalt nicht gefunden", |
|||
"Summary": "Zusammenfassung", |
|||
"MostRead": "Meist gelesen", |
|||
"Latest": "Neueste", |
|||
"ContributeAbpCommunity": "Tragen Sie zur ABP Community bei", |
|||
"SubmitYourArticle": "Reichen Sie Ihren Beitrag ein", |
|||
"ContributionGuide": "Leitfaden für Mitwirkende", |
|||
"BugReport": "Fehler melden", |
|||
"SeeAllArticles": "Alle Beiträge anzeigen", |
|||
"WelcomeToABPCommunity!": "Willkommen in der ABP Community!", |
|||
"MyProfile": "Mein Profil", |
|||
"MyOrganizations": "Meine Organisationen", |
|||
"EmailNotValid": "Bitte geben Sie eine gültige E-Mail-Adresse ein.", |
|||
"FeatureRequest": "Featureanfrage", |
|||
"CreateArticleTitleInfo": "Titel des Beitrags, der in der Beitragsliste angezeigt werden soll.", |
|||
"CreateArticleUrlInfo": "Original GitHub-/externe URL des Beitrags.", |
|||
"CreateArticleSummaryInfo": "Eine kurze Zusammenfassung des Beitrags, der in der Beitragsliste angezeigt werden soll.", |
|||
"CreateArticleCoverInfo": "Fügen Sie zum Erstellen eines effektiven Beitrags ein Titelbild hinzu. Laden Sie Bilder mit einem Seitenverhältnis von 16: 9 hoch, um die beste Ansicht zu erhalten.", |
|||
"ThisExtensionIsNotAllowed": "Diese Erweiterung ist nicht zulässig.", |
|||
"TheFileIsTooLarge": "Die Datei ist zu groß.", |
|||
"GoToTheArticle": "Gehe zum Beitrag", |
|||
"Contribute": "Beitragen", |
|||
"OverallProgress": "Gesamtfortschritt", |
|||
"Done": "Fertig", |
|||
"Open": "Offen", |
|||
"Closed": "Geschlossen", |
|||
"LatestQuestionOnThe": "Letzte Frage zum", |
|||
"Stackoverflow": "Stackoverflow", |
|||
"Votes": "Stimmen", |
|||
"Answer": "Antwort", |
|||
"Views": "Ansichten", |
|||
"Answered": "Beantwortet", |
|||
"WaitingForYourAnswer": "Warten auf Ihre Antwort", |
|||
"Asked": "gefragt", |
|||
"AllQuestions": "Alle Fragen", |
|||
"NextVersion": "Nächste Version", |
|||
"MilestoneErrorMessage": "Die aktuellen Meilensteindetails konnten von Github nicht abgerufen werden.", |
|||
"QuestionItemErrorMessage": "Die neuesten Fragendetails konnten von Stackoverflow nicht abgerufen werden.", |
|||
"Oops": "Hoppla!", |
|||
"CreateArticleSuccessMessage": "Der Beitrag wurde erfolgreich eingereicht. Er wird nach einer Überprüfung durch den Site-Administrator veröffentlicht.", |
|||
"ChooseCoverImage": "Ein Titelbild auswählen...", |
|||
"CoverImage": "Titelbild", |
|||
"ShareYourExperiencesWithTheABPFramework": "Ihre Erfahrungen mit dem ABP Framework teilen!", |
|||
"Optional": "Optional", |
|||
"UpdateUserWebSiteInfo": "Beispiel: https://johndoe.com", |
|||
"UpdateUserTwitterInfo": "Beispiel: johndoe", |
|||
"UpdateUserGithubInfo": "Beispiel: johndoe", |
|||
"UpdateUserLinkedinInfo": "Beispiel: https://www.linkedin.com/...", |
|||
"UpdateUserCompanyInfo": "Beispiel: Volosoft", |
|||
"UpdateUserJobTitleInfo": "Beispiel: Software Developer", |
|||
"UserName": "Benutzername", |
|||
"Company": "Firma", |
|||
"PersonalWebsite": "Persönliche Website", |
|||
"RegistrationDate": "Registrierungsdatum", |
|||
"Social": "Social", |
|||
"Biography": "Biographie", |
|||
"HasNoPublishedArticlesYet": "hat noch keine Beiträge veröffentlicht", |
|||
"Author": "Autor", |
|||
"LatestGithubAnnouncements": "Neueste Github-Ankündigungen", |
|||
"SeeAllAnnouncements": "Alle Ankündigungen anzeigen", |
|||
"LatestBlogPost": "Letzter Blog-Beitrag", |
|||
"Edit": "Bearbeiten", |
|||
"ProfileImageChange": "Ändern Sie das Profilbild", |
|||
"BlogItemErrorMessage": "Die neuesten Blogpost-Details konnten nicht abgerufen werden.", |
|||
"PlannedReleaseDate": "Geplantes Erscheinungsdatum", |
|||
"CommunityArticleRequestErrorMessage": "Die Anfrage nach den neuesten Beiträgen von Github konnte nicht abgerufen werden." |
|||
} |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
{ |
|||
"culture": "es", |
|||
"texts": { |
|||
"Permission:CommunityArticle": "Artículo de comunidad", |
|||
"Permission:Edit": "Editar", |
|||
"Waiting": "Esperando", |
|||
"Approved": "Aprobado", |
|||
"Rejected": "Rechazado", |
|||
"Wait": "Esperar", |
|||
"Approve": "Aprobar", |
|||
"Reject": "Rechazar", |
|||
"ReadArticle": "Leer artículo", |
|||
"Status": "Estado", |
|||
"ContentSource": "Fuente de contenido", |
|||
"Details": "Detalles", |
|||
"Url": "Url", |
|||
"Title": "Título", |
|||
"CreationTime": "Fecha de creación", |
|||
"Save": "Guardar", |
|||
"SameUrlAlreadyExist": "La url ya existe si tu quieres añadir este artículo, tu debes cambiar la url!", |
|||
"UrlIsNotValid": "Url no es valida", |
|||
"UrlNotFound": "Url no encontrada", |
|||
"UrlContentNotFound": "Contenido de la Url no encontrado", |
|||
"Summary": "Resumen", |
|||
"MostRead": "Más leído", |
|||
"Latest": "Últimos", |
|||
"ContributeAbpCommunity": "Contribuye a la comunidad ABP", |
|||
"SubmitYourArticle": "Envía tu artículo", |
|||
"ContributionGuide": "Guía de contribución", |
|||
"BugReport": "Informe de errores", |
|||
"SeeAllArticles": "Ver todos los artículos", |
|||
"WelcomeToABPCommunity!": "Bienvenido a la comunidad ABP", |
|||
"MyProfile": "Mi perfil", |
|||
"MyOrganizations": "Mis organizaciones", |
|||
"EmailNotValid": "Por favor entra una dirección de email válida.", |
|||
"FeatureRequest": "Solucitud de característica", |
|||
"CreateArticleTitleInfo": "Título del artículo para ser mostrado en la lista de artículos.", |
|||
"CreateArticleUrlInfo": "Url original del artículo GitHub/ Externo", |
|||
"CreateArticleSummaryInfo": "Un pequeño resumen del artículo para ser mostrado en la lista de artículos.", |
|||
"CreateArticleCoverInfo": "Para crear un artículo eficaz, agregue una foto de portada. Cargue imágenes con una relación de aspecto de 16: 9 para obtener la mejor vista.", |
|||
"ThisExtensionIsNotAllowed": "Esta extensión no está permitida.", |
|||
"TheFileIsTooLarge": "El fichero es demasiado grande.", |
|||
"GoToTheArticle": "Ir a el artículo", |
|||
"Contribute": "Contribuir", |
|||
"OverallProgress": "Progreso general", |
|||
"Done": "Hecho", |
|||
"Open": "Abrir", |
|||
"Closed": "Cerrado", |
|||
"LatestQuestionOnThe": "Última pregunta en la", |
|||
"Stackoverflow": "Stackoverflow", |
|||
"Votes": "Votos", |
|||
"Answer": "Respuesta", |
|||
"Views": "Vistas", |
|||
"Answered": "Respondido", |
|||
"WaitingForYourAnswer": "Esperando tu respuesta", |
|||
"Asked": "Preguntado", |
|||
"AllQuestions": "Todas las preguntas", |
|||
"NextVersion": "Siguiente versión", |
|||
"MilestoneErrorMessage": "No se pudieron obtener los detalles del hito actual en Github.", |
|||
"QuestionItemErrorMessage": "no se pudieron obtener los detalles de pregunta actual en Stackoverflow.", |
|||
"Oops": "Oops!", |
|||
"CreateArticleSuccessMessage": "El artículo se ha enviado correctamente. Se publicará después de una revisión del administrador del sitio.", |
|||
"ChooseCoverImage": "Elige una imagen de portada...", |
|||
"CoverImage": "Imagen de portada", |
|||
"ShareYourExperiencesWithTheABPFramework": "Comparte tus experiencias con el ABP Framework!", |
|||
"Optional": "Opcional", |
|||
"UpdateUserWebSiteInfo": "Ejemplo: https://johndoe.com", |
|||
"UpdateUserTwitterInfo": "Ejemplo: johndoe", |
|||
"UpdateUserGithubInfo": "Ejemplo: johndoe", |
|||
"UpdateUserLinkedinInfo": "Ejemplo: https://www.linkedin.com/...", |
|||
"UpdateUserCompanyInfo": "Ejemplo: Volosoft", |
|||
"UpdateUserJobTitleInfo": "Ejemplo: desarrollador de software", |
|||
"UserName": "Nombre de usuario", |
|||
"Company": "Empresa", |
|||
"PersonalWebsite": "Sitio web personal", |
|||
"RegistrationDate": "Fecha de registro", |
|||
"Social": "Social", |
|||
"Biography": "Biografía", |
|||
"HasNoPublishedArticlesYet": "No has publicado articules todavía", |
|||
"Author": "Autor", |
|||
"LatestGithubAnnouncements": "Últimas notificaciones de Github", |
|||
"SeeAllAnnouncements": "Ver todos las notificaciones", |
|||
"LatestBlogPost": "", |
|||
"Edit": "Editar", |
|||
"ProfileImageChange": "Cambiar la imagen de perfil", |
|||
"BlogItemErrorMessage": "No se pudo obtener los detalles del último blog desde ABP.", |
|||
"PlannedReleaseDate": "Fecha de entrega planificada", |
|||
"CommunityArticleRequestErrorMessage": "No se pudo obtener la última petición de artículo desde Github" |
|||
} |
|||
} |
|||
@ -1,64 +1,89 @@ |
|||
{ |
|||
"culture": "zh-Hans", |
|||
"texts": { |
|||
"Permission:CommunityArticle": "社区文章", |
|||
"Permission:Edit": "修改", |
|||
"Waiting": "等待中", |
|||
"Approved": "已批准", |
|||
"Rejected": "已拒绝", |
|||
"Wait": "等待", |
|||
"Approve": "批准", |
|||
"Reject": "拒绝", |
|||
"ReadArticle": "阅读文章", |
|||
"Status": "状态", |
|||
"ContentSource": "内容来源", |
|||
"Details": "详情", |
|||
"Url": "url", |
|||
"Title": "标题", |
|||
"CreationTime": "创建时间", |
|||
"Save": "保存", |
|||
"SameUrlAlreadyExist": "url已存在,如果你想要添加这篇文章,你需要更改url!", |
|||
"UrlIsNotValid": "Url无效.", |
|||
"UrlNotFound" : "Url未找到.", |
|||
"UrlContentNotFound": "Url内容未找到.", |
|||
"Summary": "摘要", |
|||
"MostRead": "阅读最多", |
|||
"Latest": "最新", |
|||
"ContributeAbpCommunity": "为ABP社区做贡献", |
|||
"SubmitYourArticle": "提交你的文章", |
|||
"ContributionGuide": "贡献指南", |
|||
"BugReport": "Bug报告", |
|||
"SeeAllArticles": "查看所有的文章", |
|||
"WelcomeToABPCommunity!": "欢迎来到ABP社区!", |
|||
"MyProfile": "我的资料", |
|||
"MyOrganizations": "我的组织", |
|||
"EmailNotValid": "请输入有效的电子邮箱地址.", |
|||
"FeatureRequest": "功能请求", |
|||
"CreateArticleTitleInfo": "文章标题显示在文章列表中.", |
|||
"CreateArticleUrlInfo": "文章的原始GitHub/外部URL.", |
|||
"CreateArticleSummaryInfo": "文章的简短摘要将显示在文章列表中.", |
|||
"CreateArticleCoverInfo": "为了创建有效的文章,请添加封面图. 仅支持16:9的图片!", |
|||
"ThisExtensionIsNotAllowed": "不允许此扩展名.", |
|||
"TheFileIsTooLarge": "文件过大.", |
|||
"GoToTheArticle": "转到文章", |
|||
"Contribute": "贡献", |
|||
"OverallProgress": "总体流程", |
|||
"Done": "完成", |
|||
"Open": "打开", |
|||
"Closed": "关闭", |
|||
"LatestQuestionOnThe": "有关的最新问题", |
|||
"Stackoverflow": "Stackoverflow", |
|||
"Votes": "票数", |
|||
"Answer": "回答", |
|||
"Views": "观看次数", |
|||
"Answered": "已回答", |
|||
"WaitingForYourAnswer": "等待你的回答", |
|||
"Asked": "提问", |
|||
"AllQuestions": "所有的问题", |
|||
"NextVersion": "下一个版本", |
|||
"MilestoneErrorMessage": "无法从Github获取当前的里程碑详细信息.", |
|||
"QuestionItemErrorMessage": "无法从Stackoverflow获取最新的问题详细信息.", |
|||
"Oops": "哎呀!" |
|||
} |
|||
"culture": "zh-Hans", |
|||
"texts": { |
|||
"Permission:CommunityArticle": "社区文章", |
|||
"Permission:Edit": "修改", |
|||
"Waiting": "等待中", |
|||
"Approved": "已批准", |
|||
"Rejected": "已拒绝", |
|||
"Wait": "等待", |
|||
"Approve": "批准", |
|||
"Reject": "拒绝", |
|||
"ReadArticle": "阅读文章", |
|||
"Status": "状态", |
|||
"ContentSource": "内容来源", |
|||
"Details": "详情", |
|||
"Url": "url", |
|||
"Title": "标题", |
|||
"CreationTime": "创建时间", |
|||
"Save": "保存", |
|||
"SameUrlAlreadyExist": "url已存在,如果你想要添加这篇文章,你需要更改url!", |
|||
"UrlIsNotValid": "Url无效.", |
|||
"UrlNotFound": "Url未找到.", |
|||
"UrlContentNotFound": "Url内容未找到.", |
|||
"Summary": "摘要", |
|||
"MostRead": "阅读最多", |
|||
"Latest": "最新", |
|||
"ContributeAbpCommunity": "为ABP社区做贡献", |
|||
"SubmitYourArticle": "提交你的文章", |
|||
"ContributionGuide": "贡献指南", |
|||
"BugReport": "Bug报告", |
|||
"SeeAllArticles": "查看所有的文章", |
|||
"WelcomeToABPCommunity!": "欢迎来到ABP社区!", |
|||
"MyProfile": "我的资料", |
|||
"MyOrganizations": "我的组织", |
|||
"EmailNotValid": "请输入有效的电子邮箱地址.", |
|||
"FeatureRequest": "功能请求", |
|||
"CreateArticleTitleInfo": "文章标题显示在文章列表中.", |
|||
"CreateArticleUrlInfo": "文章的原始GitHub/外部URL.", |
|||
"CreateArticleSummaryInfo": "文章的简短摘要将显示在文章列表中.", |
|||
"CreateArticleCoverInfo": "为了创建有效的文章,请添加封面图. 仅支持16:9的图片!", |
|||
"ThisExtensionIsNotAllowed": "不允许此扩展名.", |
|||
"TheFileIsTooLarge": "文件过大.", |
|||
"GoToTheArticle": "转到文章", |
|||
"Contribute": "贡献", |
|||
"OverallProgress": "总体流程", |
|||
"Done": "完成", |
|||
"Open": "打开", |
|||
"Closed": "关闭", |
|||
"LatestQuestionOnThe": "有关的最新问题", |
|||
"Stackoverflow": "Stackoverflow", |
|||
"Votes": "票数", |
|||
"Answer": "回答", |
|||
"Views": "观看次数", |
|||
"Answered": "已回答", |
|||
"WaitingForYourAnswer": "等待你的回答", |
|||
"Asked": "提问", |
|||
"AllQuestions": "所有的问题", |
|||
"NextVersion": "下一个版本", |
|||
"MilestoneErrorMessage": "无法从Github获取当前的里程碑详细信息.", |
|||
"QuestionItemErrorMessage": "无法从Stackoverflow获取最新的问题详细信息.", |
|||
"Oops": "哎呀!", |
|||
"CreateArticleSuccessMessage": "文章提交成功. 网站管理员审核通过后将被发布.", |
|||
"ChooseCoverImage": "选项一张封面图片", |
|||
"CoverImage": "封面图片", |
|||
"ShareYourExperiencesWithTheABPFramework": "分享你的ABP Framework经验!", |
|||
"Optional": "可选的", |
|||
"UpdateUserWebSiteInfo": "示例: https://johndoe.com", |
|||
"UpdateUserTwitterInfo": "示例: johndoe", |
|||
"UpdateUserGithubInfo": "示例: johndoe", |
|||
"UpdateUserLinkedinInfo": "示例: https://www.linkedin.com/...", |
|||
"UpdateUserCompanyInfo": "示例v: Volosoft", |
|||
"UpdateUserJobTitleInfo": "示例: Software Developer", |
|||
"UserName": "用户名", |
|||
"Company": "公司", |
|||
"PersonalWebsite": "个人网站", |
|||
"RegistrationDate": "注册时间", |
|||
"Social": "社交", |
|||
"Biography": "传记", |
|||
"HasNoPublishedArticlesYet": "尚未发表文章", |
|||
"Author": "作者", |
|||
"LatestGithubAnnouncements": "最新的Github公告", |
|||
"SeeAllAnnouncements": "查看所有公告", |
|||
"LatestBlogPost": "最新博客文章", |
|||
"Edit": "修改", |
|||
"ProfileImageChange": "更改资料图片", |
|||
"BlogItemErrorMessage": "无法从ABP获取最新的博客文章详细信息.", |
|||
"PlannedReleaseDate": "计划发布日期" |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,189 @@ |
|||
{ |
|||
"culture": "de-DE", |
|||
"texts": { |
|||
"GetStarted": "Erste Schritte - Startvorlagen", |
|||
"Create": "Erstellen", |
|||
"NewProject": "Neues Projekt", |
|||
"DirectDownload": "Direkter Download", |
|||
"ProjectName": "Proejktname", |
|||
"ProjectType": "Projekttyp", |
|||
"DatabaseProvider": "Datenbankanbieter", |
|||
"NTier": "N-Tier", |
|||
"IncludeUserInterface": "Benutzeroberfläche einschließen", |
|||
"CreateNow": "Jetzt erstellen", |
|||
"TheStartupProject": "Das Startprojekt", |
|||
"Tutorial": "Lernprogramm", |
|||
"UsingCLI": "mit CLI", |
|||
"SeeDetails": "Details ansehen", |
|||
"AbpShortDescription": "ABP Framework ist eine vollständige Infrastruktur zum Erstellen moderner Webanwendungen unter Befolgung von Best Practices und Konventionen für Softwareentwicklung.", |
|||
"SourceCodeUpper": "QUELLCODE", |
|||
"LatestReleaseLogs": "Akteulle Release", |
|||
"Infrastructure": "Infrastrutkur", |
|||
"Architecture": "Architektur", |
|||
"Modular": "Modular", |
|||
"DontRepeatYourself": "Don't Repeat Yourself", |
|||
"DeveloperFocused": "Entwickler-Zentriert", |
|||
"FullStackApplicationInfrastructure": "Full-Stack-Anwendungsinfrastruktur.", |
|||
"DomainDrivenDesign": "Domain Driven Design", |
|||
"DomainDrivenDesignExplanation": "Entworfen und entwickelt basierend auf DDD-Mustern und -Prinzipien. Bietet ein Schichtenmodell für Ihre Anwendung.", |
|||
"Authorization": "Authorization", |
|||
"AuthorizationExplanation": "Erweiterte Autorisierung mit Benutzer-, Rollen- und fein abgestimmtem Berechtigungssystem. Aufbauend auf der Microsoft Identity-Bibliothek.", |
|||
"MultiTenancy": "Multi-Tenancy", |
|||
"MultiTenancyExplanationShort": "SaaS-Anwendungen leicht gemacht! Integrierte Mandantenfähigkeit von der Datenbank bis zur Benutzeroberfläche.", |
|||
"CrossCuttingConcerns": "Cross Cutting Concerns", |
|||
"CrossCuttingConcernsExplanationShort": "Komplette Infrastruktur für Autorisierung, Validierung, Ausnahmebehandlung, Caching, Überwachungsprotokollierung, Transaktionsverwaltung und mehr.", |
|||
"BuiltInBundlingMinification": "Built-In Bundling & Minification", |
|||
"BuiltInBundlingMinificationExplanation": "Für die Bundling und Minification müssen keine externen Tools verwendet werden. ABP bietet eine einfachere, dynamische, leistungsstarke, modulare und integrierte Methode!", |
|||
"VirtualFileSystem": "Virtual File System", |
|||
"VirtualFileSystemExplanation": "Betten Sie Ansichten, Skripte, Stile, Bilder ... in Pakete/Bibliotheken ein und verwenden Sie sie in verschiedenen Anwendungen wieder.", |
|||
"Theming": "Theming", |
|||
"ThemingExplanationShort": "Verwenden und passen Sie das Bootstrap-basierte Standard-UI-Design an oder erstellen Sie Ihr eigenes.", |
|||
"BootstrapTagHelpersDynamicForms": "Bootstrap Tag Helpers & Dynamic Forms", |
|||
"BootstrapTagHelpersDynamicFormsExplanation": "Anstatt die sich wiederholenden Details von Bootstrap-Komponenten manuell zu schreiben, verwenden Sie die Tag-Helper von ABP, um diese zu vereinfachen und dabei die Vorteile von Intellisense zu nutzen. Erstellen Sie mit dem dynamischen Formular-Tag-Helfer schnell UI-Formulare basierend auf einem C#-Modell.", |
|||
"HTTPAPIsDynamicProxies": "HTTP APIs & Dynamic Proxies", |
|||
"HTTPAPIsDynamicProxiesExplanation": "Stellen Sie Anwendungsdienste automatisch als HTTP-APIs im REST-Stil bereit und verwenden Sie diese mit dynamischen JavaScript- und C#-Proxys.", |
|||
"CompleteArchitectureInfo": "Moderne Architektur zur Erstellung wartbarer Softwarelösungen.", |
|||
"DomainDrivenDesignBasedLayeringModelExplanation": "Hilft Ihnen bei der Implementierung einer DDD-basierten Schichtarchitektur und beim Aufbau einer wartbaren Codebasis.", |
|||
"DomainDrivenDesignBasedLayeringModelExplanationCont": "Bietet Startvorlagen, Abstraktionen, Basisklassen, Dienste, Dokumentation und Anleitungen, mit denen Sie Ihre Anwendung basierend auf DDD-Mustern und -Prinzipien entwickeln können.", |
|||
"MicroserviceCompatibleModelExplanation": "Das Kernframework und die vorgefertigten Module sind unter Berücksichtigung der Microservice-Architektur konzipiert.", |
|||
"MicroserviceCompatibleModelExplanationCont": "Bietet Infrastruktur, Integrationen, Beispiele und Dokumentation zur einfacheren Implementierung von Microservice-Lösungen, ohne zusätzliche Komplexität zu verursachen, wenn Sie eine monolithische Anwendung wünschen.", |
|||
"ModularInfo": "ABP bietet ein Modulsystem, mit dem Sie wiederverwendbare Anwendungsmodule entwickeln, Ereignisse im Anwendungslebenszyklus verknüpfen und Abhängigkeiten zwischen Kernteilen Ihres Systems ausdrücken können.", |
|||
"PreBuiltModulesThemes": "Vorgefertigte Module & Themes", |
|||
"PreBuiltModulesThemesExplanation": "Open Source- und kommerzielle Module und Themes stehen bereit, um in Ihrer Geschäftsanwendung verwendet zu werden.", |
|||
"NuGetNPMPackages": "NuGet- & NPM-Pakete", |
|||
"NuGetNPMPackagesExplanation": "Bereitgestellt als NuGet- & NPM-Pakete. Einfach zu installieren und zu aktualisieren.", |
|||
"ExtensibleReplaceable": "Erweiterbar/Austauschbar", |
|||
"ExtensibleReplaceableExplanation": "Alle Dienste und Module sind auf Erweiterbarkeit ausgelegt. Sie können Dienste, Seiten, Stile und Komponenten ersetzen.", |
|||
"CrossCuttingConcernsExplanation2": "Halten Sie Ihre Codebasis kleiner, damit Sie sich auf ihre geschäftsspezifischen Code konzentrieren können.", |
|||
"CrossCuttingConcernsExplanation3": "Verbringen Sie keine Zeit damit, grundlegende Anwendungsanforderungen für jedes neue Projekte zu implementieren.", |
|||
"AuthenticationAuthorization": "Authentifizierung & Autorisierung", |
|||
"ExceptionHandling": "Fehlerbehandlung", |
|||
"Validation": "Validierung", |
|||
"DatabaseConnection": "Datenbankverbindung", |
|||
"TransactionManagement": "Transaktionsmanagement", |
|||
"AuditLogging": "Audit Logging", |
|||
"Caching": "Caching", |
|||
"Multitenancy": "Multimandantenfähigkeit", |
|||
"DataFiltering": "Datenfilterung", |
|||
"ConventionOverConfiguration": "Convention Over Configuration", |
|||
"ConventionOverConfigurationExplanation": "ABP implementiert standardmäßig allgemeine Anwendungskonventionen mit einer minimalen oder Null-Konfiguration.", |
|||
"ConventionOverConfigurationExplanationList1": "Automatische Registrierung bekannter Services für Dependency Injection.", |
|||
"ConventionOverConfigurationExplanationList2": "Stellt Anwendungsdienste mittels Namenskonventionen als HTTP-APIs bereit.", |
|||
"ConventionOverConfigurationExplanationList3": "Erstellt dynamische HTTP-Client-Proxys für C# und JavaScript.", |
|||
"ConventionOverConfigurationExplanationList4": "Bietet Standard-Repositorys für Ihre Entities.", |
|||
"ConventionOverConfigurationExplanationList5": "Verwaltet die Unit-of-Work gemäß Webanforderung oder Anwendungsdienstmethode.", |
|||
"ConventionOverConfigurationExplanationList6": "Triggert Erstellungs-, Aktualisierungs- und Lösch-Events für Ihre Entities.", |
|||
"BaseClasses": "Basisklassen", |
|||
"BaseClassesExplanation": "Vorgefertigte Basisklassen für gängige Anwendungsmuster.", |
|||
"DeveloperFocusedExplanation": "ABP ist für Entwickler", |
|||
"DeveloperFocusedExplanationCont": "Es zielt darauf ab, Ihre tägliche Softwareentwicklung zu vereinfachen, ohne Sie daran zu hindern, Low-Level-Code zu schreiben.", |
|||
"SeeAllFeatures": "Alle Features anzeigen", |
|||
"CLI_CommandLineInterface": "CLI (Command Line Interface)", |
|||
"CLI_CommandLineInterfaceExplanation": "Enthält eine CLI, mit der Sie die Erstellung neuer Projekte und das Hinzufügen neuer Module automatisieren können.", |
|||
"StartupTemplates": "Startvorlagen", |
|||
"StartupTemplatesExplanation": "Verschiedene Startvorlagen bieten eine vollständig konfigurierte Lösung, um Ihre Entwicklung zu beschleunigen.", |
|||
"BasedOnFamiliarTools": "Basierend auf vertrauten Tools", |
|||
"BasedOnFamiliarToolsExplanation": "Aufbauend auf und integriert mit beliebten Tools, die Sie bereits kennen. Geringe Lernkurve, einfache Anpassung, komfortable Entwicklung.", |
|||
"ORMIndependent": "ORM-unabhängig", |
|||
"ORMIndependentExplanation": "Das Kernframework ist ORM-/datenbankunabhängig und kann mit jeder Datenquelle arbeiten. Entity Framework Core- und MongoDB-Anbieter sind bereits verfügbar.", |
|||
"Features": "Entdecken Sie die ABP Framework-Features", |
|||
"ABPCLI": "ABP CLI", |
|||
"Modularity": "Modularität", |
|||
"BootstrapTagHelpers": "Bootstrap Tag Helpers", |
|||
"DynamicForms": "Dynamische Formulare", |
|||
"BundlingMinification": "Bundling & Minification", |
|||
"BackgroundJobs": "Background Jobs", |
|||
"BackgroundJobsExplanation": "Definieren Sie einfache Klassen, um Jobs im Hintergrund in der Warteschlange auszuführen. Verwenden Sie den integrierten Jobmanager oder integrieren Sie Ihren eigenen. <a href=\"{0}\"> Hangfire </a> & <a href=\"{1}\"> RabbitMQ </a> -Integrationen sind bereits verfügbar.", |
|||
"DDDInfrastructure": "DDD-Infrastruktur", |
|||
"DomainDrivenDesignInfrastructure": "Domain Driven Design-Infrastruktur", |
|||
"AutoRESTAPIs": "Auto REST APIs", |
|||
"DynamicClientProxies": "Dynamische Client-Proxies", |
|||
"DistributedEventBus": "Distributed Event Bus", |
|||
"DistributedEventBusWithRabbitMQIntegration": "Distributed Event Bus mit RabbitMQ-Integration", |
|||
"TestInfrastructure": "Test-Infrastruktur", |
|||
"AuditLoggingEntityHistories": "Audit Logging & Entity Histories", |
|||
"ObjectToObjectMapping": "Object to Object Mapping", |
|||
"ObjectToObjectMappingExplanation": "<a href=\"{0}\"> Object to Object Mapping </a> Abstraktion mit AutoMapper-Integration.", |
|||
"EmailSMSAbstractions": "E-Mail & SMS Abstraktionen", |
|||
"EmailSMSAbstractionsWithTemplatingSupport": "E-Mail- und SMS-Abstraktionen mit Vorlagenunterstützung", |
|||
"Localization": "Lokalisierung", |
|||
"SettingManagement": "Einstellungsverwaltung", |
|||
"ExtensionMethods": "Erweiterungsmethoden", |
|||
"ExtensionMethodsHelpers": "Erweiterungsmethoden & Helfer", |
|||
"AspectOrientedProgramming": "Aspektorientierte Programmierung", |
|||
"DependencyInjection": "Dependency Injection", |
|||
"DependencyInjectionByConventions": "Dependency Injection durch Konventionen", |
|||
"ABPCLIExplanation": "ABP CLI (Command Line Interface) ist ein Befehlszeilenprogramm zum Ausführen einiger gängiger Vorgänge für ABP-basierte Lösungen.", |
|||
"ModularityExplanation": "ABP bietet eine vollständige Infrastruktur zum Erstellen eigener Anwendungsmodule, die Entities, Services, Datenbankintegration, APIs, UI-Komponenten usw. enthalten können.", |
|||
"MultiTenancyExplanation": "Das ABP-Framework unterstützt nicht nur die Entwicklung von Multi-Mandantenanwendungen, sondern macht Ihren Code von der Mandantenfähigkeit auch weitgehend unabhängig.", |
|||
"MultiTenancyExplanation2": "Kann den aktuellen Mandanten automatisch ermitteln und Daten verschiedener Mandanten voneinander isolieren.", |
|||
"MultiTenancyExplanation3": "Unterstützt einzelne Datenbank-, Datenbank-pro-Mandanten- und Hybrid-Ansätze.", |
|||
"MultiTenancyExplanation4": "Sie konzentrieren sich auf Ihren geschäftsspezifischen Code und lassen das Framework die Mandantenfähigkeit für Sie übernehmen.", |
|||
"BootstrapTagHelpersExplanation": "Anstatt die sich wiederholenden Details von Bootstrap-Komponenten manuell zu schreiben, verwenden Sie die Tag-Helper von ABP, um diese zu vereinfachen und dabei die Vorteile von Intellisense zu nutzen. Sie können Bootstrap weitherhin verwenden, wann immer Sie es benötigen.", |
|||
"DynamicFormsExplanation": "Helfer für dynamische Formular- und Input-Tags können das vollständige Formular anhand einer C#-Klasse als Model erstellen.", |
|||
"AuthenticationAuthorizationExplanation": "Umfangreiche Authentifizierungs- und Autorisierungsoptionen, die in ASP.NET Core Identity & IdentityServer4 integriert sind. Bietet ein erweiterbares und detailliertes Berechtigungssystem.", |
|||
"CrossCuttingConcernsExplanation": "Wiederholen Sie sich nicht, um all diese allgemeinen Dinge immer wieder zu implementieren. Konzentrieren Sie sich auf Ihren geschäftsspezifischen Code und lassen Sie ihn von ABP durch Konventionen automatisieren.", |
|||
"DatabaseConnectionTransactionManagement": "Datenbankverbindungs- und Transaktionsmanagement", |
|||
"CorrelationIdTracking": "Correlation-ID-Verfolgung", |
|||
"BundlingMinificationExplanation": "ABP bietet ein einfaches, dynamisches, leistungsstarkes, modulares und integriertes Bundling- und Minification-System.", |
|||
"VirtualFileSystemnExplanation": "Das virtuelle Dateisystem ermöglicht die Verwaltung von Dateien, die physisch nicht auf dem Dateisystem (Datenträger) vorhanden sind. Es wird hauptsächlich verwendet, um Dateien (js, css, image, cshtml ...) in Assemblys einzubetten und sie zur Laufzeit wie physische Dateien zu verwenden.", |
|||
"ThemingExplanation": "Mit dem Theming-System können Sie Ihre Anwendung & Module Theme-unabhängig entwickeln, indem Sie eine Reihe gemeinsamer Basisbibliotheken und Layouts definieren, die auf dem neuesten Bootstrap-Framework basieren.", |
|||
"DomainDrivenDesignInfrastructureExplanation": "Eine vollständige Infrastruktur zum Erstellen von mehrschichtigen Anwendungen basierend auf den Domain Driven Design Entwurfsmustern und -prinzipien;", |
|||
"Specification": "Specification", |
|||
"Repository": "Repository", |
|||
"DomainService": "Domain Service", |
|||
"ValueObject": "Value Object", |
|||
"ApplicationService": "Application Service", |
|||
"DataTransferObject": "Data Transfer Object", |
|||
"AggregateRootEntity": "Aggregate Root, Entity", |
|||
"AutoRESTAPIsExplanation": "ABP kann Ihre Anwendungsservices gemäß Konvention automatisch als API-Controller konfigurieren.", |
|||
"DynamicClientProxiesExplanation": "Verwenden Sie Ihre APIs ganz einfach in JavaScript- und C#-Clients.", |
|||
"DistributedEventBusWithRabbitMQIntegrationExplanation": "Veröffentlichen und konsumieren Sie Distributed Events einfach mithilfe des integrierten Distributed Event Bus mit verfügbarer RabbitMQ-Integration.", |
|||
"TestInfrastructureExplanation": "Das Framework wurde unter Berücksichtigung von Unit- und Integrationstests entwickelt. Bietet Ihnen Basisklassen, um es einfacher zu machen. Startvorlagen werden mit vorkonfiguriert Tests geliefert.", |
|||
"AuditLoggingEntityHistoriesExplanation": "Integriertes Audit Logging für geschäftskritische Anwendungen. Audit Logging auf Request-, Service-, und Methodenebene sowie Entity-Historien mit Details auf Property-Ebene.", |
|||
"EmailSMSAbstractionsWithTemplatingSupportExplanation": "IEmailSender- und ISmsSender-Abstraktionen entkoppeln Ihre Anwendungslogik von der Infrastruktur. Das erweiterte E-Mail-Vorlagensystem ermöglicht das Erstellen und Lokalisieren von E-Mail-Vorlagen und deren einfache Verwendung bei Bedarf.", |
|||
"LocalizationExplanation": "Das Lokalisierungssystem ermöglicht das Erstellen von Ressourcen in einfachen JSON-Dateien und die Lokalisierung Ihrer Benutzeroberfläche. Es unterstützt erweiterte Szenarien wie Vererbung, Erweiterungen und JavaScript-Integration und ist vollständig mit dem Lokalisierungssystem von AspNet Core kompatibel.", |
|||
"SettingManagementExplanation": "Definieren Sie Einstellungen für Ihre Anwendung und erhalten Sie zur Laufzeit Werte basierend auf der aktuellen Konfiguration, dem Mandanten und dem Benutzer.", |
|||
"ExtensionMethodsHelpersExplanation": "Wiederholen Sie sich nicht einmal für triviale Codeteile. Erweiterungen und Helfer für Standardtypen machen Ihren Code viel sauberer und einfacher zu schreiben.", |
|||
"AspectOrientedProgrammingExplanation": "Bietet eine komfortable Infrastruktur zum Erstellen dynamischer Proxys und zum Implementieren der aspektorientierten Programmierung. Fangen Sie eine Klasse ab und führen Sie Ihren Code vor und nach jeder Methodenausführung aus.", |
|||
"DependencyInjectionByConventionsExplanation": "Sie müssen Ihre Klassen nicht manuell für die Dependency Injection registrieren. Registriert gängige Servicetypen automatisch gemäß Konvention. Für andere Arten von Services können Sie Schnittstellen und Attribute verwenden, um dies einfacher gestalten und an Ort und Stelle zu ermöglichen.", |
|||
"DataFilteringExplanation": "Definieren und verwenden Sie Datenfilter, die automatisch angewendet werden, wenn Sie Entities aus der Datenbank abfragen. Soft Delete- und Multimandanten-Filter sind sofort verfügbar, wenn Sie einfache Schnittstellen implementieren.", |
|||
"PublishEvents": "Events veröffentlichen", |
|||
"HandleEvents": "Auf Events reagieren", |
|||
"AndMore": "und mehr...", |
|||
"Code": "Code", |
|||
"Result": "Resultat", |
|||
"SeeTheDocumentForMoreInformation": "Weitere Informationen finden Sie in der <a href=\"{1}\"> {0} -Dokumentation </a>", |
|||
"IndexPageHeroSection": "<span class=\"first-line shine\"><strong>Open Source</strong></span><span class=\"second-line text-uppercase\">Webanwendung<br />Framework </span><span class=\"third-line shine2\"><strong>für ASP.Net Core</strong></span>", |
|||
"UiFramework": "UI-Framework", |
|||
"EmailAddress": "E-Mail-Adresse", |
|||
"Mobile": "Mobile", |
|||
"ReactNative": "React Native", |
|||
"Strong": "Stark", |
|||
"Complete": "Vollständig", |
|||
"BasedLayeringModel": "Based Layering Model", |
|||
"Microservice": "Microservice", |
|||
"Compatible": "Kompatibel", |
|||
"MeeTTheABPCommunityInfo": "Unsere Mission ist es, eine Umgebung zu schaffen, in der Entwickler sich gegenseitig mit Beiträgen, Tutorials, Fallstudien usw. helfen und Gleichgesinnte treffen können.", |
|||
"JoinTheABPCommunityInfo": "Beteiligen Sie sich an einer lebendigen Community und tragen Sie zum ABP Framework bei!", |
|||
"AllArticles": "Alle Beiträge", |
|||
"SubmitYourArticle": "Reichen Sie Ihren Beitrag ein", |
|||
"DynamicClientProxyDocument": "In der Dokumentation zu den Dynamischen Client-Proxies finden Sie Informationen zu <a href=\"{0}\">JavaScript</a> & <a href=\"{1}\">C#</a>.", |
|||
"EmailSMSAbstractionsDocument": "Weitere Informationen finden Sie in den Unterlagen <a href=\"{0}\">E-Mail-Senden</a> and <a href=\"{1}\">SMS-Senden</a>.", |
|||
"CreateProjectWizard": "Dieser Assistent erstellt ein neues Projekt aus der Startvorlage, die ordnungsgemäß konfiguriert ist, um Ihr Projekt zu starten.", |
|||
"TieredOption": "Erstellt eine Tiered Lösung, bei der Web- und HTTP-API-Ebenen physisch getrennt sind. Wenn diese Option nicht aktiviert ist, wird eine mehrschichtige Lösung erstellt, die weniger komplex und für die meisten Szenarien geeignet ist.", |
|||
"SeparateIdentityServerOption": "Trennt die Serverseite in zwei Anwendungen: Die erste ist für den Identitätsserver und die zweite für die serverseitige HTTP-API.", |
|||
"UseslatestPreVersion": "Verwendet die neueste Vorabversion", |
|||
"ReadTheDocumentation": "<span class=\"text-primary\">Lesen Sie</span><span class=\"text-success\">Die Dokumentation</span>", |
|||
"Documentation": "Dokumentation", |
|||
"GettingStartedTutorial": "Erste Schritte Tutorial", |
|||
"ApplicationDevelopmentTutorial": "Tutorial zur Anwendungsentwicklung", |
|||
"TheStartupTemplate": "Die Startvorlage", |
|||
"InstallABPCLIInfo": "ABP CLI ist der schnellste Weg, um eine neue Lösung mit dem ABP-Framework zu starten. Installieren Sie die ABP-CLI über die Eingabeaufforderung:", |
|||
"DifferentLevelOfNamespaces": "Sie können verschiedene Ebenen von Namespaces verwenden; z.B. BookStore, Acme.BookStore or Acme.Retail.BookStore.", |
|||
"ABPCLIExamplesInfo": "Der Befehl <strong>new</strong> erstellt eine <strong>mehrschichtige MVC-Anwendung</strong> mit <strong>Entity Framework Core</strong> als Datenbankanbieter. Es gibt jedoch zusätzliche Optionen. Beispiele:", |
|||
"SeeCliDocumentForMoreInformation": "Weitere Optionen finden Sie im <a href=\"{0}\">ABP CLI-Dokument</a> oder wählen Sie oben die Registerkarte \"Direkter Download\".", |
|||
"Optional": "Optional", |
|||
"LocalFrameworkRef": "Behalten Sie die lokale Projektreferenz für die Framework-Pakete bei." |
|||
} |
|||
} |
|||
@ -0,0 +1,189 @@ |
|||
{ |
|||
"culture": "es", |
|||
"texts": { |
|||
"GetStarted": "Comencemos - Plantillas de inicio", |
|||
"Create": "Crear", |
|||
"NewProject": "Nuevo proyecto", |
|||
"DirectDownload": "Descarga directa", |
|||
"ProjectName": "Nombre de proyecto", |
|||
"ProjectType": "Tipo de proyecto", |
|||
"DatabaseProvider": "Proveedor de base de datos", |
|||
"NTier": "N-Capas", |
|||
"IncludeUserInterface": "Incluir interface de usuario", |
|||
"CreateNow": "Crear ahora", |
|||
"TheStartupProject": "El proyecto de inicio", |
|||
"Tutorial": "Tutorial", |
|||
"UsingCLI": "Usando CLI", |
|||
"SeeDetails": "Ver detalles", |
|||
"AbpShortDescription": "ABP Framework es una completa infraestructure para crear modernas aplicaciones web que sigue las mejores prácticas y convenciones de desarrollo de software.", |
|||
"SourceCodeUpper": "CÓDIGO FUENTE", |
|||
"LatestReleaseLogs": "Últimos registros de lanzamiento", |
|||
"Infrastructure": "infraestructura", |
|||
"Architecture": "Arquitectura", |
|||
"Modular": "Modular", |
|||
"DontRepeatYourself": "No te repitas tu mismo", |
|||
"DeveloperFocused": "Pensado para el desarrollador", |
|||
"FullStackApplicationInfrastructure": "infraestructura de aplicación Full stack", |
|||
"DomainDrivenDesign": "", |
|||
"DomainDrivenDesignExplanation": "Diseñado y desarrollado basandose en los patrones y principios de DDD. Promorciona una capa de modelo para tus aplicaciones.", |
|||
"Authorization": "Autorización", |
|||
"AuthorizationExplanation": "Sistema de autorización avanzado con usuarios, roles y permisos de granularidad-fina. Construido sobre la librería Microsoft Identity.", |
|||
"MultiTenancy": "Multi-inquilino", |
|||
"MultiTenancyExplanationShort": "Aplicaciones SaaS sencillas!, integradas con multi-inquilino desde la base de datos hasta la UI.", |
|||
"CrossCuttingConcerns": "Requerimientos comunes", |
|||
"CrossCuttingConcernsExplanationShort": "Completa infraestructura de autorización, validación, manejo de excepciones, caching, auditoría, gestión de transacciones y más.", |
|||
"BuiltInBundlingMinification": "Empaquetado y minificado integrado", |
|||
"BuiltInBundlingMinificationExplanation": "No se necesitan usar herramientas externas para el empaquetado y minificado. ABP ofrece un camino simple, dinámico, potente, modular e integrado.", |
|||
"VirtualFileSystem": "Sistema de ficheros virtual", |
|||
"VirtualFileSystemExplanation": "Incrusta vistas, scripts, estilos, imágenes en paquetes/ librerias y reusalos en diferentes aplicaciones.", |
|||
"Theming": "Temas", |
|||
"ThemingExplanationShort": "Usa y personaliza la UI estandar basada en bootstrap o crea tu propio tema.", |
|||
"BootstrapTagHelpersDynamicForms": "Boostrap Tag Helpers y formularios dinámicos", |
|||
"BootstrapTagHelpersDynamicFormsExplanation": "", |
|||
"HTTPAPIsDynamicProxies": "HTTP APIs y proxies dinámicos", |
|||
"HTTPAPIsDynamicProxiesExplanation": "Expon servicios de aplicación como REST HTPP APIs y consumelos dinámicamente desde proxies JavaScript y C#.", |
|||
"CompleteArchitectureInfo": "Arquitectura moderna para crear soluciones software sostenibles.", |
|||
"DomainDrivenDesignBasedLayeringModelExplanation": "Ayuda a implementar ", |
|||
"DomainDrivenDesignBasedLayeringModelExplanationCont": "Promorciona plantillas de inicio, clases base, servicios, documentación y guías de ayuda para desarrollar tu aplicación basada en patrones y principios DDD.", |
|||
"MicroserviceCompatibleModelExplanation": "El núcleo del framework y los modules pre-construidos están diseñados con una arquitectura microservicios en mente.", |
|||
"MicroserviceCompatibleModelExplanationCont": "Proporciona la infraestructura, integraciones, ejemplos y documentación para implementar soluciones microservicios más facilmente, mientras no trae complejidad adicional si quieres una aplicación monolítica.", |
|||
"ModularInfo": "ABP proporciona un sistema de modulos que te permite desarrollar modulos de aplicacion resusables. Conectado en el ciclo de eventos de aplicación y mínimas dependencias entre las partes principales de tu sistema.", |
|||
"PreBuiltModulesThemes": "Modulos y temas integrados", |
|||
"PreBuiltModulesThemesExplanation": "Módulos y temas de código abierto y comerciales preparados para usar en tu aplicación de negocio.", |
|||
"NuGetNPMPackages": "Paquetes Nuget y NPM", |
|||
"NuGetNPMPackagesExplanation": "Paquetes distribuidos a través de Nuget y NPM para instalar y actualizar.", |
|||
"ExtensibleReplaceable": "Extensible/ Reemplazable", |
|||
"ExtensibleReplaceableExplanation": "Todos los serivios y módulos están diseñados para ser extensibles. Tu puedes reemplazar servicios, páginas, estilos y componentes.", |
|||
"CrossCuttingConcernsExplanation2": "Mantiene tu código base más pequeño y te permite enforcate en el código que es especifico en tu negocio.", |
|||
"CrossCuttingConcernsExplanation3": "No pierdas tiempo implementando requerimientos comunes de aplicación en múltiples proyectos.", |
|||
"AuthenticationAuthorization": "Autenticación y autorización", |
|||
"ExceptionHandling": "Manejo de excepciones.", |
|||
"Validation": "Validación", |
|||
"DatabaseConnection": "Conexión a la base de datos", |
|||
"TransactionManagement": "Gestión de transacciones", |
|||
"AuditLogging": "Registro de auditoría", |
|||
"Caching": "Caché", |
|||
"Multitenancy": "Multi-inquilino", |
|||
"DataFiltering": "Filtrado de datos", |
|||
"ConventionOverConfiguration": "Convención sobre la configuración", |
|||
"ConventionOverConfigurationExplanation": "ABP implementa comunes convenciones de aplicación por defecto con una mínima o nula configuración.", |
|||
"ConventionOverConfigurationExplanationList1": "Los registradores conocen los servicios para la inyección de dependencias.", |
|||
"ConventionOverConfigurationExplanationList2": "Expone servicios de aplicación como APIs HTTP mediante convenciones de nomenclatura.", |
|||
"ConventionOverConfigurationExplanationList3": "Crea clientes proxies HTTP dinámicos para C# y JavaScript.", |
|||
"ConventionOverConfigurationExplanationList4": "Proporciona repositorios por defecto para tus entidades.", |
|||
"ConventionOverConfigurationExplanationList5": "Maneja Unit of Work por cada petición web o metodo de servicio de aplicación.", |
|||
"ConventionOverConfigurationExplanationList6": "Publica, crea, actualiza y borra eventos para tus entidades.", |
|||
"BaseClasses": "Clase base", |
|||
"BaseClassesExplanation": "Clases base integradas para patrones comunes de aplicación.", |
|||
"DeveloperFocusedExplanation": "ABP es para desarrolladores.", |
|||
"DeveloperFocusedExplanationCont": "Su objetivo es simplificar su desarrollo diario de software sin restringirle la escritura de código de bajo nivel.", |
|||
"SeeAllFeatures": "Ver todas las características", |
|||
"CLI_CommandLineInterface": "CLI (Command Line Interface)", |
|||
"CLI_CommandLineInterfaceExplanation": "Incluye un CLI que te ayuda a automatizar la creación de nuevos proyectos y añadir nuevos módulos.", |
|||
"StartupTemplates": "Plantillas de inicio", |
|||
"StartupTemplatesExplanation": "Varias plantillas de inicio proporcionan una solución completamente configurada lista para comenzar el desarrollo.", |
|||
"BasedOnFamiliarTools": "Basado en herramientas familiares", |
|||
"BasedOnFamiliarToolsExplanation": "Construido y diseñado con herramientas populares que tu ya conoces. Baja curva de aprendizaje, facil adaptación y desarrollo confortable.", |
|||
"ORMIndependent": "Independiente del ORM", |
|||
"ORMIndependentExplanation": "El núcleo del core es independiente del ORM/ base de datos y puedes trabajar con cualquier fuente de datos. Entity Framework Core y MongoDB están actualmente disponibles.", |
|||
"Features": "Explora las características de ABP Framework", |
|||
"ABPCLI": "ABP CLI", |
|||
"Modularity": "Modularidad", |
|||
"BootstrapTagHelpers": "Bootstrap Tag Helpers", |
|||
"DynamicForms": "Formularios dinámicos", |
|||
"BundlingMinification": "Empaquetado y Minimificación", |
|||
"BackgroundJobs": "", |
|||
"BackgroundJobsExplanation": "Defina clases simples para ejecutar trabajos en segundo plano como en cola. Utilice el administrador de trabajos integrado o integre el suyo propio. <a href=\"{0}\">Hangfire</a> & <a href=\"{1}\">RabbitMQ</a> integraciones están actualmente disponibles.", |
|||
"DDDInfrastructure": "infraestructura DSS", |
|||
"DomainDrivenDesignInfrastructure": "infraestructura Domain Driven Design", |
|||
"AutoRESTAPIs": "Auto REST APIs", |
|||
"DynamicClientProxies": "Clientes proxies dinámicos", |
|||
"DistributedEventBus": "Bus de eventos distribuido", |
|||
"DistributedEventBusWithRabbitMQIntegration": "Bus de eventos distribuido con la integración RabbitMQ ", |
|||
"TestInfrastructure": "infraestructura de Test", |
|||
"AuditLoggingEntityHistories": "Registro de auditoría y historial de entidades", |
|||
"ObjectToObjectMapping": "Mapeado objeto a objeto", |
|||
"ObjectToObjectMappingExplanation": "<a href=\"{0}\">Mapeado objeto a objeto</a> abstracción integrada con AutoMapper.", |
|||
"EmailSMSAbstractions": "Abstracciones para Email y SMS", |
|||
"EmailSMSAbstractionsWithTemplatingSupport": "Abstracciones para Email y SMS con soporte para plantillas", |
|||
"Localization": "Localización", |
|||
"SettingManagement": "Gestión de la configuración", |
|||
"ExtensionMethods": "Extension Methods", |
|||
"ExtensionMethodsHelpers": "Extension Methods & Helpers", |
|||
"AspectOrientedProgramming": "Programación orientada a aspectos", |
|||
"DependencyInjection": "Inyección de dependencias", |
|||
"DependencyInjectionByConventions": "Inyección de dependencias por convenciones", |
|||
"ABPCLIExplanation": "ABP CLI (Command Line Interface) es una herramienta en línea de comandos que proporciona ciertas tareas comunes para soluciones basadas en ABP.", |
|||
"ModularityExplanation": "ABP proporciona una infraestructura completa para construir tu propios módulos de aplicación que pueden contener entidades, servicios, base de datos integradas, APIs, componentes de UI y otros...", |
|||
"MultiTenancyExplanation": "ABP framework no sólo soporta el desarrollo de aplicaciones multi-inquilino, si no también hace que tu código no tenga que preocuparse de multi-inquilino.", |
|||
"MultiTenancyExplanation2": "Puedes determinar automaticamente el inquilino actual, y aislar los datos de diferentes inquilinos entre sí. ", |
|||
"MultiTenancyExplanation3": "Soporta base de datos única, base de datos por inquilino y enfoques híbridos.", |
|||
"MultiTenancyExplanation4": "Enfocate en tu código y deja al framework que maneje multi-inquilino en tu nombre.", |
|||
"BootstrapTagHelpersExplanation": "En vez de escribir repetidamente los detalle de componentes bootstrap, usa ABP's tag helpers para simplificarlo y obtener ventaja de intellisence. Tu puedes definitivamente usar Bootstrp cuando tu lo necesites.", |
|||
"DynamicFormsExplanation": "Los formularios dinámicos y tag helpers de entrada pueden crear el formulario completo a partir de una clase de C# como modelo. ", |
|||
"AuthenticationAuthorizationExplanation": "Autenticación enriquecidad y opciones de autorización integradas con ASP.NET Core Identity & IdentityServer4. Proporciona un extensible y detallado sistema de permisos.", |
|||
"CrossCuttingConcernsExplanation": "No te repitas tu mismo al implementar todas esas cosas comunes una y otra vez. Enfocate en tu negocio y permite a ABP automatizarlos por convención.", |
|||
"DatabaseConnectionTransactionManagement": "Conexión de base de datos y gestión de transacciones", |
|||
"CorrelationIdTracking": "Correlation-Id de seguimiento", |
|||
"BundlingMinificationExplanation": "ABP ofrece un sistema simple, dinámico, potente, modular y empaquetado & minificación ", |
|||
"VirtualFileSystemnExplanation": "El sistema de archivos virtuales permite administrar archivos que no existen físicamente en el sistema de archivos (disco). Se utiliza principalmente para incrustar (js, css, image, cshtml...) en ensamblados y utilizarlos como archivos físicos en tiempo de ejecución.", |
|||
"ThemingExplanation": "El sistema de temas permite desarrollar el tema de su aplicación y módulos independiente mediante la definición de un conjunto de bibliotecas y diseños base comunes, basado en el último marco de Trabajo bootstrap.", |
|||
"DomainDrivenDesignInfrastructureExplanation": "Una infraestructura completa para crear aplicaciones en capas basadas en los patrones y principios DDD", |
|||
"Specification": "Especificación", |
|||
"Repository": "Repositorios", |
|||
"DomainService": "Servicio de dominio", |
|||
"ValueObject": "Objetos de valor", |
|||
"ApplicationService": "Servicio de aplicación", |
|||
"DataTransferObject": "Objetos de transferencia de datos", |
|||
"AggregateRootEntity": "Agregado ráiz, Entidad", |
|||
"AutoRESTAPIsExplanation": "ABP puede configurar automáticamente los servicios de aplicación como controladores de API por convención.", |
|||
"DynamicClientProxiesExplanation": "Consuma fácilmente sus API de clientes de JavaScript y C#", |
|||
"DistributedEventBusWithRabbitMQIntegrationExplanation": "Publique y consuma eventos distribuidos fácilmente mediante el bus de eventos distribuido integrado con la integración RabbitMQ disponible.", |
|||
"TestInfrastructureExplanation": "El framework se ha desarrollado unitariamente y pruebas de integración. Proporciona clases base para que sea más fácil. Las plantillas de inicio vienen preconfiguradas para las pruebas.", |
|||
"AuditLoggingEntityHistoriesExplanation": "Registro de auditoría integrado para aplicaciones críticas para el negocio. Registro de auditorías de solicitud, servicio, nivel de método e historiales de entidades con detalles de nivel de propiedad.", |
|||
"EmailSMSAbstractionsWithTemplatingSupportExplanation": "Las abstracciones IEmailSender e ISmsSender desacoplan la lógica de la aplicación de la infraestructura. El sistema avanzado de plantillas de correo electrónico permite crear y localizar plantillas de correo electrónico y utilizarlas fácilmente cuando sea necesario.", |
|||
"LocalizationExplanation": "El sistema de localización permite crear recursos en archivos JSON sin formato y utilizarlos para localizar la interfaz de usuario. Admite escenarios avanzados como herencia, extensiones e integración de JavaScript, mientras que es totalmente compatible con el sistema de localización de AspNet Core.", |
|||
"SettingManagementExplanation": "Defina la configuración de la aplicación y obtenga valores en tiempo de ejecución en función de la configuración actual, el inquilino y el usuario.", |
|||
"ExtensionMethodsHelpersExplanation": "No te repitas ni siquiera para partes de código triviales. Extensiones y ayudantes para tipos estándar hace que su código sea mucho más limpio y fácil de escribir.", |
|||
"AspectOrientedProgrammingExplanation": "Proporciona una infraestructura cómoda para crear servidores proxy dinámicos e implementar la programación orientada a aspectos. Interceptar cualquier clase y ejecutar el código antes y después de cada ejecución del método.", |
|||
"DependencyInjectionByConventionsExplanation": "No es necesario registrar las clases en la inserción de dependencias manualmente. Registra automáticamente los tipos de servicio comunes por convención. Para otro tipo de servicios, puede utilizar interfaces y atributos para que sea más fácil y in situ.", |
|||
"DataFilteringExplanation": "Definir y usar filtros de datos que se aplican automáticamente al consultar entidades desde la base de datos. Los filtros Soft Delete & MultiTenant se proporcionan de fábrica cuando se implementan interfaces sencillas.", |
|||
"PublishEvents": "Publicar eventos", |
|||
"HandleEvents": "Manejar eventos", |
|||
"AndMore": "y más...", |
|||
"Code": "Código", |
|||
"Result": "Resultado", |
|||
"SeeTheDocumentForMoreInformation": "Ver el <a href=\"{1}\">{0} documento</a> para más información.", |
|||
"IndexPageHeroSection": "<span class=\"first-line shine\"><strong>Código fuente abierto</strong></span><span class=\"second-line text-uppercase\">Web Application<br />Framework </span><span class=\"third-line shine2\"><strong>para asp.net core</strong></span>", |
|||
"UiFramework": "UI Framework", |
|||
"EmailAddress": "Dirección de correo", |
|||
"Mobile": "Móvil", |
|||
"ReactNative": "React Nativo", |
|||
"Strong": "Fuerte", |
|||
"Complete": "Completar", |
|||
"BasedLayeringModel": "Módelo basado en capas", |
|||
"Microservice": "Microservicio", |
|||
"Compatible": "Compatible", |
|||
"MeeTTheABPCommunityInfo": "Nuestra misión es crear un entorno en el que los desarrolladores puedan ayudarse entre sí con artículos, tutoriales, estudios de casos, etc. y conocer personas de ideas afines.", |
|||
"JoinTheABPCommunityInfo": "¡Participe en una comunidad vibrante y conviértase en colaborador del Marco ABP!", |
|||
"AllArticles": "Todos los artículos", |
|||
"SubmitYourArticle": "Envía tu artículo", |
|||
"DynamicClientProxyDocument": "Ver la documentación del cliente proxy dinámico para <a href=\"{0}\">JavaScript</a> & <a href=\"{1}\">C#</a>.", |
|||
"EmailSMSAbstractionsDocument": "Ver los documentos de <a href=\"{0}\">emailing</a> y <a href=\"{1}\">envío SMS </a> para más información.", |
|||
"CreateProjectWizard": "Este asistente crea un nuevo proyecto a partir de la plantilla de inicio que está correctamente configurado para comenzar con su proyecto.", |
|||
"TieredOption": "Crea una solución por niveles en la que las capas de API Web y HTTP están separadas físicamente. Si no se marca, crea una solución en capas que es menos compleja y adecuada para la mayoría de los escenarios.", |
|||
"SeparateIdentityServerOption": "Separa el lado del servidor en dos aplicaciones: la primera es para el servidor de identidad y la segunda es para la API HTTP del lado del servidor.", |
|||
"UseslatestPreVersion": "Usar la última versión pre-release", |
|||
"ReadTheDocumentation": "<span class=\"text-primary\">Leer</span><span class=\"text-success\">La Documentación</span>", |
|||
"Documentation": "Documentación", |
|||
"GettingStartedTutorial": "Tutorial para iniciarse", |
|||
"ApplicationDevelopmentTutorial": "Tutorial de desarrollo de aplicación", |
|||
"TheStartupTemplate": "La Plantilla de Inicio", |
|||
"InstallABPCLIInfo": "ABP CLI es la forma más rápida de iniciar una nueva solución con el marco ABP. Instale la CLI de ABP mediante una ventana de línea de comandos:", |
|||
"DifferentLevelOfNamespaces": "Tu puedes usar diferentes niveles de espacio de nombres; ej. BookStore, Acme.BookStore or Acme.Retail.BookStore.", |
|||
"ABPCLIExamplesInfo": "<strong>nuevo</strong> comando crea una <strong>aplicación MVC por capas</strong> con <strong>Entity Framework Core</strong> como proveedor de base de datos. Sin embargo, tiene distintas opciones. Ejemplos:", |
|||
"SeeCliDocumentForMoreInformation": "Ver el <a href=\"{0}\">documento ABP CLI </a> para más opciones o selecciona la \"Direct Download\" pestaña de arriba.", |
|||
"Optional": "Opcional", |
|||
"LocalFrameworkRef": "Mantén la referencia al proyecto local para los paquetes del framework." |
|||
} |
|||
} |
|||
@ -1,32 +1,3 @@ |
|||
# Social/External Logins |
|||
|
|||
The [Account Module](../Modules/Account.md) has already configured to handle social or external logins out of the box. You can follow the ASP.NET Core documentation to add a social/external login provider to your application. |
|||
|
|||
## Example: Facebook Authentication |
|||
|
|||
Follow the [ASP.NET Core Facebook integration document](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/facebook-logins) to support the Facebook login for your application. |
|||
|
|||
#### Add the NuGet Package |
|||
|
|||
Add the [Microsoft.AspNetCore.Authentication.Facebook](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.Facebook) package to your project. Based on your architecture, this can be `.Web`, `.IdentityServer` (for tiered setup) or `.Host` project. |
|||
|
|||
#### Configure the Provider |
|||
|
|||
Use the `.AddFacebook(...)` extension method in the `ConfigureServices` method of your [module](../Module-Development-Basics.md), to configure the client: |
|||
|
|||
````csharp |
|||
context.Services.AddAuthentication() |
|||
.AddFacebook(facebook => |
|||
{ |
|||
facebook.AppId = "..."; |
|||
facebook.AppSecret = "..."; |
|||
facebook.Scope.Add("email"); |
|||
facebook.Scope.Add("public_profile"); |
|||
}); |
|||
```` |
|||
|
|||
> It would be a better practice to use the `appsettings.json` or the ASP.NET Core User Secrets system to store your credentials, instead of a hard-coded value like that. Follow the [Microsoft's document](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/facebook-logins) to learn the user secrets usage. |
|||
|
|||
## Angular UI |
|||
|
|||
Beginning from the v3.1, the Angular UI uses authorization code flow (as a best practice) to authenticate the user by redirecting to the MVC UI login page. So, even if you are using the Angular UI, social/external login integration is same as explained above and it will work out of the box. |
|||
> This document has been moved. See the [Account Module](../Modules/Account.md) documentation. |
|||
@ -1,3 +1,133 @@ |
|||
# RabbitMQ Background Job Manager |
|||
|
|||
TODO |
|||
RabbitMQ is an industry standard message broker. While it is typically used for inter-process communication (messaging / distributed events), it is pretty useful to store and execute background jobs in FIFO (First In First Out) order. |
|||
|
|||
ABP Framework provides the [Volo.Abp.BackgroundJobs.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.RabbitMQ) NuGet package to use the RabbitMQ for background job execution. |
|||
|
|||
> See the [background jobs document](Background-Jobs.md) to learn how to use the background job system. This document only shows how to install and configure the RabbitMQ integration. |
|||
|
|||
## Installation |
|||
|
|||
Use the ABP CLI to add [Volo.Abp.BackgroundJobs.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.RabbitMQ) NuGet package to your project: |
|||
|
|||
* Install the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) if you haven't installed before. |
|||
* Open a command line (terminal) in the directory of the `.csproj` file you want to add the `Volo.Abp.BackgroundJobs.RabbitMQ` package. |
|||
* Run `abp add-package Volo.Abp.BackgroundJobs.RabbitMQ` command. |
|||
|
|||
If you want to do it manually, install the [Volo.Abp.BackgroundJobs.RabbitMQ](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.RabbitMQ) NuGet package to your project and add `[DependsOn(typeof(AbpBackgroundJobsRabbitMqModule))]` to the [ABP module](Module-Development-Basics.md) class inside your project. |
|||
|
|||
## Configuration |
|||
|
|||
### Default Configuration |
|||
|
|||
The default configuration automatically connects to the local RabbitMQ server (localhost) with the standard port. **In this case, no configuration needed.** |
|||
|
|||
### RabbitMQ Connection(s) |
|||
|
|||
You can configure the RabbitMQ connections using the standard [configuration system](Configuration.md), like using the `appsettings.json` file, or using the [options](Options.md) classes. |
|||
|
|||
#### `appsettings.json` file configuration |
|||
|
|||
This is the simplest way to configure the RabbitMQ connections. It is also very strong since you can use any other configuration source (like environment variables) that is [supported by the AspNet Core](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/). |
|||
|
|||
**Example: Configuring the Default RabbitMQ Connection** |
|||
|
|||
````json |
|||
{ |
|||
"RabbitMQ": { |
|||
"Connections": { |
|||
"Default": { |
|||
"HostName": "123.123.123.123", |
|||
"Port": "5672" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
You can use any of the [ConnectionFactry](http://rabbitmq.github.io/rabbitmq-dotnet-client/api/RabbitMQ.Client.ConnectionFactory.html#properties) properties as the connection properties. See [the RabbitMQ document](https://www.rabbitmq.com/dotnet-api-guide.html#exchanges-and-queues) to understand these options better. |
|||
|
|||
Defining multiple connections is allowed. In this case, you can use different connections for different background job types (see the `AbpRabbitMqBackgroundJobOptions` section below). |
|||
|
|||
**Example: Declare two connections** |
|||
|
|||
````json |
|||
{ |
|||
"RabbitMQ": { |
|||
"Connections": { |
|||
"Default": { |
|||
"HostName": "123.123.123.123" |
|||
}, |
|||
"SecondConnection": { |
|||
"HostName": "321.321.321.321" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
#### AbpRabbitMqOptions |
|||
|
|||
`AbpRabbitMqOptions` class can be used to configure the connection strings for the RabbitMQ. You can configure this options inside the `ConfigureServices` of your [module](Module-Development-Basics.md). |
|||
|
|||
**Example: Configure the connection** |
|||
|
|||
````csharp |
|||
Configure<AbpRabbitMqOptions>(options => |
|||
{ |
|||
options.Connections.Default.UserName = "user"; |
|||
options.Connections.Default.Password = "pass"; |
|||
options.Connections.Default.HostName = "123.123.123.123"; |
|||
options.Connections.Default.Port = 5672; |
|||
}); |
|||
```` |
|||
|
|||
Using these options classes can be combined with the `appsettings.json` way. Configuring an option property in the code overrides the value in the configuration file. |
|||
|
|||
### AbpRabbitMqBackgroundJobOptions |
|||
|
|||
#### Job Queue Names |
|||
|
|||
By default, each job type uses a separate queue. Queue names are calculated by combining a standard prefix and the job name. Default prefix is `AbpBackgroundJobs.` So, if the job name is `EmailSending` then the queue name in the RabbitMQ becomes `AbpBackgroundJobs.EmailSending` |
|||
|
|||
> Use `BackgroundJobName` attribute on the background **job argument** class to specify the job name. Otherwise, the job name will be the full name (with namespace) of the job class. |
|||
|
|||
#### Job Connections |
|||
|
|||
By default, all the job types use the `Default` RabbitMQ connection. |
|||
|
|||
#### Customization |
|||
|
|||
`AbpRabbitMqBackgroundJobOptions` can be used to customize the queue names and the connections used by the jobs. |
|||
|
|||
**Example:** |
|||
|
|||
````csharp |
|||
Configure<AbpRabbitMqBackgroundJobOptions>(options => |
|||
{ |
|||
options.DefaultQueueNamePrefix = "my_app_jobs."; |
|||
options.JobQueues[typeof(EmailSendingArgs)] = |
|||
new JobQueueConfiguration( |
|||
typeof(EmailSendingArgs), |
|||
queueName: "my_app_jobs.emails", |
|||
connectionName: "SecondConnection" |
|||
); |
|||
}); |
|||
```` |
|||
|
|||
* This example sets the default queue name prefix to `my_app_jobs.`. If different applications use the same RabbitMQ server, it would be important to use different prefixes for each application to not consume jobs of each other. |
|||
* Also specifies a different connection string for the `EmailSendingArgs`. |
|||
|
|||
`JobQueueConfiguration` class has some additional options in its constructor; |
|||
|
|||
* `queueName`: The queue name that is used for this job. The prefix is not added, so you need to specify the full name of the queue. |
|||
* `connectionName`: The RabbitMQ connection name (see the connection configuration above). This is optional and the default value is `Default`. |
|||
* `durable` (optional, default: `true`). |
|||
* `exclusive` (optional, default: `false`). |
|||
* `autoDelete` (optional, default: `false`) |
|||
|
|||
See the RabbitMQ documentation if you want to understand the `durable`, `exclusive` and `autoDelete` options better, while most of the times the default configuration is what you want. |
|||
|
|||
## See Also |
|||
|
|||
* [Background Jobs](Background-Jobs.md) |
|||
@ -0,0 +1,271 @@ |
|||
# ABP Framework 3.3 RC Has Been Published |
|||
|
|||
We have released the [ABP Framework](https://abp.io/) (and the [ABP Commercial](https://commercial.abp.io/)) `3.3.0-rc.1` today. This blog post introduces the new features and important changes in the new version. |
|||
|
|||
## Get Started with the 3.3 RC.1 |
|||
|
|||
If you want to try the version `3.3.0-rc.1` today, follow the steps below; |
|||
|
|||
1) **Upgrade** the ABP CLI to the version `3.3.0-rc.1` using a command line terminal: |
|||
|
|||
````bash |
|||
dotnet tool update Volo.Abp.Cli -g --version 3.3.0-rc.1 |
|||
```` |
|||
|
|||
**or install** if you haven't installed before: |
|||
|
|||
````bash |
|||
dotnet tool install Volo.Abp.Cli -g --version 3.3.0-rc.1 |
|||
```` |
|||
|
|||
2) Create a **new application** with the `--preview` option: |
|||
|
|||
````bash |
|||
abp new BookStore --preview |
|||
```` |
|||
|
|||
See the [ABP CLI documentation](https://docs.abp.io/en/abp/3.3/CLI) for all the available options. |
|||
|
|||
> You can also use the *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the Preview checkbox. |
|||
|
|||
## What's new with the ABP Framework 3.3 |
|||
|
|||
### The Blazor UI |
|||
|
|||
We had released an experimental early preview version of the Blazor UI with the [previous version](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-3.2-RC-With-The-New-Blazor-UI). In this version, we've completed most of the fundamental infrastructure features and the application modules (like identity and tenant management). |
|||
|
|||
It currently has almost the same functionalities as the other UI types (Angular & MVC / Razor Pages). |
|||
|
|||
**Example screenshot**: User management page of the Blazor UI |
|||
|
|||
 |
|||
|
|||
> We've adapted the [Lepton Theme](https://commercial.abp.io/themes) for the ABP Commercial, see the related section below. |
|||
|
|||
We are still working on the fundamentals. So, the next version may introduce breaking changes of the Blazor UI. We will work hard to keep them with the minimal effect on your application code. |
|||
|
|||
#### Breaking Changes on the Blazor UI |
|||
|
|||
There are some breaking changes with the Blazor UI. If you've built an application and upgrade it, your application might not properly work. See [the migration guide](https://docs.abp.io/en/abp/3.3/Migration-Guides/BlazorUI-3_3) for the changes you need to do after upgrading your application. |
|||
|
|||
### Automatic Validation for AntiForgery Token for HTTP APIs |
|||
|
|||
Starting with the version 3.3, all your HTTP API endpoints are **automatically protected** against CSRF attacks, unless you disable it for your application. So, no configuration needed, just upgrade the ABP Framework. |
|||
|
|||
[See the documentation](https://docs.abp.io/en/abp/3.3/CSRF-Anti-Forgery) to if you want to understand why you need it and how ABP Framework solves the problem. |
|||
|
|||
### Rebus Integration Package for the Distributed Event Bus |
|||
|
|||
[Rebus](https://github.com/rebus-org/Rebus) describes itself as "Simple and lean service bus implementation for .NET". There are a lot of integration packages like RabbitMQ and Azure Service Bus for the Rebus. The new [Volo.Abp.EventBus.Rebus](https://www.nuget.org/packages/Volo.Abp.EventBus.Rebus) package allows you to use the Rebus as the [distributed event bus](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus) for the ABP Framework. |
|||
|
|||
See [the documentation](https://docs.abp.io/en/abp/3.3/Distributed-Event-Bus-Rebus-Integration) to learn how to use Rebus with the ABP Framework. |
|||
|
|||
### Async Repository LINQ Extension Methods |
|||
|
|||
You have a problem when you want to use **Async LINQ Extension Methods** (e.g. `FirstOrDefaultAsync(...)`) in your **domain** and **application** layers. These async methods are **not included in the standard LINQ extension methods**. Those are defined by the [Microsoft.EntityFrameworkCore](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore) NuGet package (see [the code](https://github.com/dotnet/efcore/blob/main/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs)). To be able to use these `async` methods, you need to reference to the `Microsoft.EntityFrameworkCore` package. |
|||
|
|||
If you don't want to depend on the EF Core in your business layer, then ABP Framework provides the `IAsyncQueryableExecuter` service to execute your queries asynchronously without depending on the EF Core package. You can see [the documentation](https://docs.abp.io/en/abp/latest/Repositories#option-3-iasyncqueryableexecuter) to get more information about this service. |
|||
|
|||
ABP Framework version 3.3 takes this one step further and allows you to directly execute the async LINQ extension methods on the `IRepository` interface. |
|||
|
|||
**Example: Use `CountAsync` and `FirstOrDefaultAsync` methods on the repositories** |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Domain.Repositories; |
|||
|
|||
namespace MyCompanyName.MyProjectName |
|||
{ |
|||
public class BookAppService : ApplicationService, IBookAppService |
|||
{ |
|||
private readonly IRepository<Book, Guid> _bookRepository; |
|||
|
|||
public BookAppService(IRepository<Book, Guid> bookRepository) |
|||
{ |
|||
_bookRepository = bookRepository; |
|||
} |
|||
|
|||
public async Task DemoAsync() |
|||
{ |
|||
var countAll = await _bookRepository |
|||
.CountAsync(); |
|||
|
|||
var count = await _bookRepository |
|||
.CountAsync(x => x.Name.Contains("A")); |
|||
|
|||
var book1984 = await _bookRepository |
|||
.FirstOrDefaultAsync(x => x.Name == "1984"); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
All the standard LINQ methods are supported: *AllAsync, AnyAsync, AverageAsync, ContainsAsync, CountAsync, FirstAsync, FirstOrDefaultAsync, LastAsync, LastOrDefaultAsync, LongCountAsync, MaxAsync, MinAsync, SingleAsync, SingleOrDefaultAsync, SumAsync, ToArrayAsync, ToListAsync*. |
|||
|
|||
This approach still has a limitation. You need to execute the extension method directly on the repository object. For example, the below usage is **not supported**: |
|||
|
|||
````csharp |
|||
var count = await _bookRepository.Where(x => x.Name.Contains("A")).CountAsync(); |
|||
```` |
|||
|
|||
This is because the object returned from the `Where` method is not a repository object, it is a standard `IQueryable`. In such cases, you can still use the `IAsyncQueryableExecuter`: |
|||
|
|||
````csharp |
|||
var count = await AsyncExecuter.CountAsync( |
|||
_bookRepository.Where(x => x.Name.Contains("A")) |
|||
); |
|||
```` |
|||
|
|||
`AsyncExecuter` has all the standard extension methods, so you don't have any restriction here. See [the repository documentation](https://docs.abp.io/en/abp/latest/Repositories#iqueryable-async-operations) for all the options you have. |
|||
|
|||
> ABP Framework does its best to not depend on the EF Core and still be able to use the async LINQ extension methods. However, there is no problem to depend on the EF Core for your application, you can add the `Microsoft.EntityFrameworkCore` NuGet package and use the native methods. |
|||
|
|||
### Stream Support for the Application Service Methods |
|||
|
|||
[Application services](https://docs.abp.io/en/abp/latest/Application-Services) are consumed by clients and the parameters and return values (typically [Data Transfer Objects](https://docs.abp.io/en/abp/latest/Data-Transfer-Objects)). In case of the client is a remote application, then these objects should be serialized & deserialized. |
|||
|
|||
Until the version 3.3, we hadn't suggest to use the `Stream` in the application service contracts, since it is not serializable/deserializable. However, with the version 3.3, ABP Framework properly supports this scenario by introducing the new `IRemoteStreamContent` interface. |
|||
|
|||
Example: An application service that can get or return streams |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Content; |
|||
|
|||
namespace MyProject.Test |
|||
{ |
|||
public interface ITestAppService : IApplicationService |
|||
{ |
|||
Task Upload(Guid id, IRemoteStreamContent streamContent); |
|||
Task<IRemoteStreamContent> Download(Guid id); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
The implementation can be as shown below: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Content; |
|||
|
|||
namespace MyProject.Test |
|||
{ |
|||
public class TestAppService : ApplicationService, ITestAppService |
|||
{ |
|||
public Task<IRemoteStreamContent> Download(Guid id) |
|||
{ |
|||
var fs = new FileStream("C:\\Temp\\" + id + ".blob", FileMode.OpenOrCreate); |
|||
return Task.FromResult( |
|||
(IRemoteStreamContent) new RemoteStreamContent(fs) { |
|||
ContentType = "application/octet-stream" |
|||
} |
|||
); |
|||
} |
|||
|
|||
public async Task Upload(Guid id, IRemoteStreamContent streamContent) |
|||
{ |
|||
using (var fs = new FileStream("C:\\Temp\\" + id + ".blob", FileMode.Create)) |
|||
{ |
|||
await streamContent.GetStream().CopyToAsync(fs); |
|||
await fs.FlushAsync(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
> This is just a demo code. Do it better in your production code :) |
|||
|
|||
Thanks to [@alexandru-bagu](https://github.com/alexandru-bagu) for the great contribution! |
|||
|
|||
### Other Changes |
|||
|
|||
* Upgraded all the .NET Core / ASP.NET Core related packages to the version 3.1.8. If you have additional dependencies to the .NET Core / ASP.NET Core related packages, we suggest you to updates your packages to the version 3.1.8 to have the latest bug and security fixes published by Microsoft. |
|||
* The blogging module now uses the [BLOB Storing](https://docs.abp.io/en/abp/latest/Blob-Storing) system to store images & files of the blog posts. If you are using this module, then you need to manually migrate the local files to the BLOB Storing system after the upgrade. |
|||
* The Angular UI is now redirecting to the profile management page of the MVC UI instead of using its own UI, if you've configured the authorization code flow (which is default since the version 3.2.0). |
|||
|
|||
## What's new with the ABP Commercial 3.3 |
|||
|
|||
### The Blazor UI |
|||
|
|||
We have good news for the ABP Commercial Blazor UI too. We have implemented the [Lepton Theme](https://commercial.abp.io/themes) integration, so it is now available with the Blazor UI. Also, implemented most of the fundamental [modules](https://commercial.abp.io/modules). |
|||
|
|||
**A screenshot from the ABP Commercial startup template with the Blazor UI** |
|||
|
|||
 |
|||
|
|||
There are still missing features and modules. However, we are working on it to have a more complete version in the next release. |
|||
|
|||
#### Breaking Changes on the Blazor UI |
|||
|
|||
There are some breaking changes with the Blazor UI. If you've built an application and upgrade it, your application might not properly work. See the [ABP Commercial Blazor UI v 3.3 Migration Guide](https://docs.abp.io/en/commercial/3.3/migration-guides/blazor-ui-3_3) for the changes you need to do after upgrading your application. |
|||
|
|||
#### Known Issues |
|||
|
|||
When you create a new project, profile management doesn't work, you get an exception because it can't find the `/libs/cropperjs/css/cropper.min.css` file. To fix the issue; |
|||
|
|||
* Add `"@volo/account": "^3.3.0-rc.1"` to the `package.json` in the `.Host` project. |
|||
* Run `yarn` (or `npm install`), then `gulp` on a command line terminal in the root folder of the `.Host` project. |
|||
|
|||
### Multi-Tenant Social Logins |
|||
|
|||
[Account module](https://commercial.abp.io/modules/Volo.Account.Pro) now supports to manage the social/external logins in the UI. You can **enable/disable** and **set options** in the settings page. It also supports to use **different credentials for the tenants** and it is also **configured on the runtime**. |
|||
|
|||
 |
|||
|
|||
### Linked Accounts |
|||
|
|||
Linked user system allows you to link other accounts (including account in a different tenant) with your account, so you can switch between different accounts with a single-click. It is practical since you no longer need to logout and login again with entering the credentials of the target account. |
|||
|
|||
To manage the linked accounts, go to the profile management page from the user menu; |
|||
|
|||
 |
|||
|
|||
### Paypal & Stripe Integrations |
|||
|
|||
The [Payment Module](https://commercial.abp.io/modules/Volo.Payment) was supporting PayU and 2Checkout providers until the version 3.3. It's now integrated to PayPal and Stripe. See the [technical documentation](https://docs.abp.io/en/commercial/latest/modules/payment) to learn how to use it. |
|||
|
|||
### ABP Suite Improvements |
|||
|
|||
We've done a lot of small improvements for the [ABP Suite](https://commercial.abp.io/tools/suite). Some of the enhancements are; |
|||
|
|||
* Show the previously installed modules as *installed* on the module list. |
|||
* Switch between the latest stable, the latest [preview](https://docs.abp.io/en/abp/latest/Previews) and the latest [nightly build](https://docs.abp.io/en/abp/latest/Nightly-Builds) versions of the ABP related packages. |
|||
* Moved the file that stores the *previously created entities* into the solution folder to allow you to store it in your source control system. |
|||
|
|||
### Others |
|||
|
|||
* Added an option to the Account Module to show reCAPTCHA on the login & the registration forms. |
|||
|
|||
Besides the new features introduced in this post, we've done a lot of small other enhancements and bug fixes to provide a better development experience and increase the developer productivity. |
|||
|
|||
## New Articles |
|||
|
|||
The core ABP Framework team & the community continue to publish new articles on the [ABP Community](https://community.abp.io/) web site. The recently published articles are; |
|||
|
|||
* [Replacing Email Templates and Sending Emails](https://community.abp.io/articles/replacing-email-templates-and-sending-emails-jkeb8zzh) (by [@EngincanV](https://community.abp.io/members/EngincanV)) |
|||
* [How to Add Custom Properties to the User Entity](https://community.abp.io/articles/how-to-add-custom-property-to-the-user-entity-6ggxiddr) (by [@berkansasmaz](https://community.abp.io/members/berkansasmaz)) |
|||
* [Using the AdminLTE Theme with the ABP Framework MVC / Razor Pages UI](https://community.abp.io/articles/using-the-adminlte-theme-with-the-abp-framework-mvc-razor-pages-ui-gssbhb7m) (by [@mucahiddanis](https://community.abp.io/members/mucahiddanis)) |
|||
* [Using DevExtreme Angular Components With the ABP Framework](https://community.abp.io/articles/using-devextreme-angular-components-with-the-abp-framework-x5nyvj3i) (by [@bunyamin](https://community.abp.io/members/bunyamin)) |
|||
|
|||
It is appreciated if you want to [submit an article](https://community.abp.io/articles/submit) related to the ABP Framework. |
|||
|
|||
## About the Next Release |
|||
|
|||
The next version will be `4.0.0`. We are releasing a major version, since we will move the ABP Framework to .NET 5.0. We see that for most of the applications this will not be a breaking change and we hope you easily upgrade to it. |
|||
|
|||
The planned 4.0.0-rc.1 (Release Candidate) version date is **November 11**, just after the Microsoft releases the .NET 5.0 final. The planned 4.0.0 final release date is **November 26**. |
|||
|
|||
Follow the [GitHub milestones](https://github.com/abpframework/abp/milestones) for all the planned ABP Framework version release dates. |
|||
|
|||
## Feedback |
|||
|
|||
Please check out the ABP Framework 3.3.0 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us to release a more stable version. The planned release date for the [3.3.0 final](https://github.com/abpframework/abp/milestone/44) version is October 27th. |
|||
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 181 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 199 KiB |
@ -0,0 +1,47 @@ |
|||
# ABP Framework & ABP Commercial 3.3 Final Have Been Released |
|||
|
|||
ABP Framework & ABP Commercial 3.3.0 have been released today. |
|||
|
|||
Since all the new features are already explained in details with the [3.3 RC Announcement Post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-v3.3-RC-Have-Been-Released), I will not repeat all the details again. Please read [the RC post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-v3.3-RC-Have-Been-Released) for **new feature and changes** you may need to do for your solution while upgrading to the version 3.3. |
|||
|
|||
## Creating New Solutions |
|||
|
|||
You can create a new solution with the ABP Framework version 3.3 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). |
|||
|
|||
> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details. |
|||
|
|||
## How to Upgrade an Existing Solution |
|||
|
|||
### Install/Update the ABP CLI |
|||
|
|||
First of all, install the ABP CLI or upgrade to the latest version. |
|||
|
|||
If you haven't installed yet: |
|||
|
|||
````bash |
|||
dotnet tool install -g Volo.Abp.Cli |
|||
```` |
|||
|
|||
To update an existing installation: |
|||
|
|||
```bash |
|||
dotnet tool update -g Volo.Abp.Cli |
|||
``` |
|||
|
|||
### ABP UPDATE Command |
|||
|
|||
[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: |
|||
|
|||
````bash |
|||
abp update |
|||
```` |
|||
|
|||
Run this command in the root folder of your solution. After the update command, check [the RC blog post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-v3.3-RC-Have-Been-Released) to learn if you need to make any changes in your solution. |
|||
|
|||
> You may want to see the new [upgrading document](https://docs.abp.io/en/abp/latest/Upgrading). |
|||
|
|||
## About the Next Version: 4.0 |
|||
|
|||
The next version will be 4.0 and it will be mostly related to completing the Blazor UI features and upgrading the ABP Framework & ecosystem to the .NET 5.0. |
|||
|
|||
The goal is to complete the version 4.0 with a stable Blazor UI with the fundamental features implemented and publish it just after the Microsoft lunches .NET 5 in this November. The planned 4.0 preview release date is November 11th. |
|||
@ -0,0 +1,143 @@ |
|||
# ABP Framework 4.0 RC Has Been Published based on .NET 5.0! |
|||
|
|||
Today, we have released the [ABP Framework](https://abp.io/) (and the [ABP Commercial](https://commercial.abp.io/)) 4.0.0 RC that is based on the **.NET 5.0**. This blog post introduces the new features and important changes in the new version. |
|||
|
|||
> **The planned release date for the [4.0.0 final](https://github.com/abpframework/abp/milestone/45) version is November 26, 2020**. |
|||
|
|||
## Get Started with the 4.0 RC |
|||
|
|||
If you want to try the version `4.0.0` today, follow the steps below; |
|||
|
|||
1) **Upgrade** the ABP CLI to the version `4.0.0-rc.3` using a command line terminal: |
|||
|
|||
````bash |
|||
dotnet tool update Volo.Abp.Cli -g --version 4.0.0-rc.3 |
|||
```` |
|||
|
|||
**or install** if you haven't installed before: |
|||
|
|||
````bash |
|||
dotnet tool install Volo.Abp.Cli -g --version 4.0.0-rc.3 |
|||
```` |
|||
|
|||
2) Create a **new application** with the `--preview` option: |
|||
|
|||
````bash |
|||
abp new BookStore --preview |
|||
```` |
|||
|
|||
See the [ABP CLI documentation](https://docs.abp.io/en/abp/3.3/CLI) for all the available options. |
|||
|
|||
> You can also use the *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. |
|||
|
|||
## Migrating From 3.x to 4.0 |
|||
|
|||
The version 4.0 comes with some major changes including the **migration from .NET Core 3.1 to .NET 5.0**. |
|||
|
|||
We've prepared a **detailed [migration document](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0)** to explain all the changes and the actions you need to take while upgrading your existing solutions. |
|||
|
|||
## What's new with the ABP Framework 4.0 |
|||
|
|||
### The Blazor UI |
|||
|
|||
The Blazor UI is now stable and officially supported. The [web application development tutorial](https://docs.abp.io/en/abp/4.0/Tutorials/Part-1?UI=Blazor) has been updated based on the version 4.0. |
|||
|
|||
#### abp bundle command |
|||
|
|||
Introducing the `abp bundle` CLI command to manage static JavaScript & CSS file dependencies of a Blazor application. This command is currently used to add the dependencies to the `index.html` file in the dependency order by respecting to modularity. In the next version it will automatically unify & minify the files. The documentation is being prepared. |
|||
|
|||
#### Removed the JQuery & Bootstrap JavaScript |
|||
|
|||
Removed JQuery & Bootstrap JavaScript dependencies for the Blazor UI. |
|||
|
|||
>There are some other changes in the startup template and some public APIs. Follow the [Migration Guide](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0) to apply changes for existing solutions that you're upgrading from the version 3.3. While we will continue to make improvements add new features, we no longer make breaking changes on the existing APIs until the version 5.0. |
|||
|
|||
#### Others |
|||
|
|||
A lot of minor and major improvements have been done for the Blazor UI. Some of them are listed below: |
|||
|
|||
* Implemented `IComponentActivator` to resolve the component from the `IServiceProvider`. So, you can now inject dependencies into the constructor of your razor component. |
|||
* Introduced the `AbpComponentBase` base class that you derive your components from. It has useful base properties that you can use in your pages/components. |
|||
* Introduced `IUiNotificationService` service to show toast notifications on the UI. |
|||
* Improved the `IUiMessageService` to show message & confirmation dialogs. |
|||
|
|||
### System.Text.Json |
|||
|
|||
ABP Framework 4.0 uses the System.Text.Json by default as the JSON serialization library. It, actually, using a hybrid approach: Continues to use the Newtonsoft.Json when it needs to use the features not supported by the System.Text.Json. |
|||
|
|||
Follow the [Migration Guide](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0) to learn how to configure to use the Newtonsoft.Json for some specific types or switch back to the Newtonsoft.Json as the default JSON serializer. |
|||
|
|||
### Identity Server 4 Upgrade |
|||
|
|||
ABP Framework upgrades the [IdentityServer4](https://www.nuget.org/packages/IdentityServer4) library from 3.x to 4.1.1 with the ABP Framework version 4.0. IdentityServer 4.x has a lot of changes. Some of them are **breaking changes in the data structure**. |
|||
|
|||
Follow the [Migration Guide](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0) to upgrade existing solutions. |
|||
|
|||
### Creating a New Module Inside the Application |
|||
|
|||
ABP CLI has now a command to create a new module and add it to an existing solution. In this way, you can create modular applications easier than before. |
|||
|
|||
Example: Create a *ProductManagement* module into your solution. |
|||
|
|||
````bash |
|||
abp add-module ProductManagement --new --add-to-solution-file |
|||
```` |
|||
|
|||
Execute this command in a terminal in the root folder of your solution. If you don't specify the `--add-to-solution-file` option, then the module projects will not be added to the main solution, but the project references still be added. In this case, you need to open the module's solution to develop the module. |
|||
|
|||
See the [CLI document](https://docs.abp.io/en/abp/4.0/CLI) for other options. |
|||
|
|||
### WPF Startup Template |
|||
|
|||
Introducing the WPF startup template for the ABP Framework. Use the ABP CLI new command to create a new WPF application: |
|||
|
|||
````bash |
|||
abp new MyWpfApp -t wpf |
|||
```` |
|||
|
|||
This is a minimalist, empty project template that is integrated to the ABP Framework. |
|||
|
|||
### New Languages |
|||
|
|||
**Thanks to the contributors** from the ABP Community, the framework modules and the startup template have been localized to **German** language by [Alexander Pilhar](https://github.com/alexanderpilhar) & [Nico Lachmuth](https://github.com/tntwist). |
|||
|
|||
### Other Notes |
|||
|
|||
* Upgraded to Angular 11. |
|||
* Since [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library not supports transactions, you can use transactions in unit tests for MongoDB. |
|||
|
|||
## What's new with the ABP Commercial 4.0 |
|||
|
|||
### The Blazor UI |
|||
|
|||
The Blazor UI for the ABP Commercial is also becomes stable and feature rich with the version 4.0; |
|||
|
|||
* [ABP Suite](https://commercial.abp.io/tools/suite) now supports to generate CRUD pages for the Blazor UI. |
|||
* Completed the [Lepton Theme](https://commercial.abp.io/themes) for the Blazor UI. |
|||
* Implemented the [File Management](https://commercial.abp.io/modules/Volo.FileManagement) module for the Blazor UI. |
|||
|
|||
### The ABP Suite |
|||
|
|||
While creating create/edit modals with a navigation property, we had two options: A dropdown to select the target entity and a modal to select the entity by searching with a data table. |
|||
|
|||
Dropdown option now supports **lazy load, search and auto-complete**. In this way, selecting a navigation property becomes much easier and supports large data sets on the dropdown. |
|||
|
|||
**Example: Select an author while creating a new book** |
|||
|
|||
 |
|||
|
|||
With the new version, you can **disable backend code generation** on CRUD page generation. This is especially useful if you want to regenerate the page with a different UI framework, but don't want to regenerate the server side code. |
|||
|
|||
### Identity Server Management UI Revised |
|||
|
|||
Completely revised the Identity Server Management UI based on the IDS 4.x changes. |
|||
|
|||
## About the Next Release |
|||
|
|||
The next feature version, `4.1.0`, will mostly focus on completing the missing documents, fixing bugs, performance optimizations and improving the Blazor UI features. The planned preview release date for the version `4.1.0` is December 10 and the final (stable) version release date is December 24. |
|||
|
|||
Follow the [GitHub milestones](https://github.com/abpframework/abp/milestones) for all the planned ABP Framework version release dates. |
|||
|
|||
## Feedback |
|||
|
|||
Please check out the ABP Framework 4.0.0 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us to release a more stable version. **The planned release date for the [4.0.0 final](https://github.com/abpframework/abp/milestone/45) version is November 26**. |
|||
|
After Width: | Height: | Size: 28 KiB |
@ -0,0 +1,87 @@ |
|||
# ABP.IO Platform 4.0 with .NET 5.0 in the 4th Year! |
|||
|
|||
Today, we are extremely happy to release ABP Framework 4.0 with **.NET 5.0 support**! |
|||
|
|||
## 4 Years of Work |
|||
|
|||
As a nice coincidence, today is the **4th year** since the first commit made in the [abp repository](https://github.com/abpframework/abp)! So, we can say "*Happy Birthday ABP Framework!*". |
|||
|
|||
 |
|||
|
|||
### Some Statistics |
|||
|
|||
ABP.IO Platform and the ABP Community is growing. Here, a summary of these 4 years. |
|||
|
|||
From GitHub, only from the main [abp repository](https://github.com/abpframework/abp); |
|||
|
|||
* **15,297 commits** done. |
|||
* **3,764 issues** are closed. |
|||
* **2,133 pull requests** are merged. |
|||
* **158 contributors**. |
|||
* **88 releases** published. |
|||
* **5.2K stars** on GitHub. |
|||
|
|||
From NuGet & NPM; |
|||
|
|||
* **220 NuGet** packages & **52 NPM** packages. |
|||
* **1,000,000 downloads** only for the core NuGet package. |
|||
|
|||
From Website; |
|||
|
|||
* **200,000 visitors**. |
|||
* **1,000,000+ sessions**. |
|||
|
|||
## What's New With 4.0? |
|||
|
|||
Since all the new features are already explained in details with the [4.0 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-v4.0-RC-Has-Been-Released-based-on-.NET-5.0), I will not repeat all the details again. Please read [the RC post](https://blog.abp.io/abp/ABP.IO-Platform-v4.0-RC-Has-Been-Released-based-on-.NET-5.0) for **new feature and changes** you may need to do for your solution while upgrading to the version 4.0. |
|||
|
|||
Here, a brief list of major features and changes; |
|||
|
|||
* Migrated to **.NET 5.0**. |
|||
* Stable **Blazor** UI. |
|||
* Moved to **System.Text.Json**. |
|||
* Upgraded to **IdentityServer** version 4.0. |
|||
* **WPF** startup template. |
|||
|
|||
## Creating New Solutions |
|||
|
|||
You can create a new solution with the ABP Framework version 4.0 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). |
|||
|
|||
> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details. |
|||
|
|||
## How to Upgrade an Existing Solution |
|||
|
|||
This is a **major version** and requires some **manual work**, especially related to **.NET 5.0** and **IdentityServer** 4.0 upgrades. |
|||
|
|||
* See the [MIGRATION GUIDE](https://docs.abp.io/en/abp/latest/Migration-Guides/Abp-4_0) that covers all the details about the upgrade progress. |
|||
|
|||
* You can also see the [upgrading document](https://docs.abp.io/en/abp/latest/Upgrading). |
|||
|
|||
## New Guides / Documents |
|||
|
|||
We are constantly improving the documentation. Our purpose is not only document the ABP Framework, but also write architectural and practical guides for developers. |
|||
|
|||
### Implementing Domain Driven Design |
|||
|
|||
[Implementing Domain Driven Design](https://docs.abp.io/en/abp/latest/Domain-Driven-Design-Implementation-Guide) is a practical guide for they want to implement the DDD principles in their solutions. While the implementation details rely on the ABP Framework infrastructure, core concepts, principles and patterns are applicable in any kind of solution, even if it is not a .NET solution. |
|||
|
|||
 |
|||
|
|||
### Testing |
|||
|
|||
The new [Testing document](https://docs.abp.io/en/abp/latest/Testing) discusses different kind of automated tests and explains how you can write tests for your ABP based solutions. |
|||
|
|||
### UI Documents |
|||
|
|||
We've created a lot of documents for the [MVC](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Overall), [Blazor](https://docs.abp.io/en/abp/latest/UI/Blazor/Overall) and the [Angular](https://docs.abp.io/en/abp/latest/UI/Angular/Quick-Start) UI. |
|||
|
|||
## About the Next Version |
|||
|
|||
The next versions 4.1 will mostly focus on; |
|||
|
|||
* Improving current features. |
|||
* Complete module features for the Blazor UI. |
|||
* Improve developer experience and productivity. |
|||
* More documentation and examples. |
|||
|
|||
Planned preview date for the version **4.1 is December 17, 2020**. See the [Road Map](https://docs.abp.io/en/abp/latest/Road-Map) document and [GitHub Milestones](https://github.com/abpframework/abp/milestones) to learn what's planned for the next versions. We are trying to be clear about the coming features and the next release dates. |
|||
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 149 KiB |
@ -0,0 +1,147 @@ |
|||
# CSRF/XSRF & Anti Forgery System |
|||
|
|||
"*Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user’s web browser to perform an unwanted action on a trusted site for which the user is currently authenticated*" ([OWASP](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet)). |
|||
|
|||
**ABP Framework completely automates CSRF preventing** and works out of the box without any configuration. Read this documentation only if you want to understand it better or need to customize. |
|||
|
|||
## The Problem |
|||
|
|||
ASP.NET Core [provides infrastructure](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery) to prevent CSRF attacks by providing a system to **generate** and **validate antiforgery tokens**. However, the standard implementation has a few drawbacks; |
|||
|
|||
Antiforgery token validation is only **enabled for razor pages by default** and not enabled for **HTTP APIs**. You need to enable it yourself for the Controllers. You can use the `[ValidateAntiForgeryToken]` attribute for a specific API Controller/Action or the `[AutoValidateAntiforgeryToken]` attribute to prevent attacks globally. |
|||
|
|||
Once you enable it; |
|||
|
|||
* You need to manually add an HTTP header, named `RequestVerificationToken` to every **AJAX request** made in your application. You should care about obtaining the token, saving in the client side and adding to the HTTP header on every HTTP request. |
|||
* All your clients, including **non-browser clients**, should care about obtaining and sending the antiforgery token in every request. In fact, non-browser clients has no CSRF risk and should not care about this. |
|||
|
|||
Especially, the second point is a pain for your clients and unnecessarily consumes your server resources. |
|||
|
|||
> You can read more about the ASP.NET Core antiforgery system in its own [documentation](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery). |
|||
|
|||
## The Solution |
|||
|
|||
ABP Framework provides `[AbpValidateAntiForgeryToken]` and `[AbpAutoValidateAntiforgeryToken]` attributes, just like the attributes explained above. `[AbpAutoValidateAntiforgeryToken]` is already added to the global filters, so you should do nothing to enable it for your application. |
|||
|
|||
ABP Framework also automates the following infrastructure; |
|||
|
|||
* Server side sets a **special cookie**, named `XSRF-TOKEN` by default, that is used make the antiforgery token value available to the browser. This is **done automatically** (by the [application configuration](API/Application-Configuration.md) endpoint). Nothing to do in the client side. |
|||
* In the client side, it reads the token from the cookie and sends it in the **HTTP header** (named `RequestVerificationToken` by default). This is implemented for all the supported UI types. |
|||
* Server side validates the antiforgery token **only for same and cross site requests** made by the browser. It bypasses the validation for non-browser clients. |
|||
|
|||
That's all. The systems works smoothly. |
|||
|
|||
## Configuration / Customization |
|||
|
|||
### AbpAntiForgeryOptions |
|||
|
|||
`AbpAntiForgeryOptions` is the main [options class](Options.md) to configure the ABP Antiforgery system. It has the following properties; |
|||
|
|||
* `TokenCookie`: Can be used to configure the cookie details. This cookie is used to store the antiforgery token value in the client side, so clients can read it and sends the value as the HTTP header. Default cookie name is `XSRF-TOKEN`, expiration time is 10 years (yes, ten years! It should be a value longer than the authentication cookie max life time, for the security). |
|||
* `AuthCookieSchemaName`: The name of the authentication cookie used by your application. Default value is `Identity.Application` (which becomes `AspNetCore.Identity.Application` on runtime). The default value properly works with the ABP startup templates. **If you change the authentication cookie name, you also must change this.** |
|||
* `AutoValidate`: The single point to enable/disable the ABP automatic antiforgery validation system. Default value is `true`. |
|||
* `AutoValidateFilter`: A predicate that gets a type and returns a boolean. ABP uses this predicate to check a controller type. If it returns false for a controller type, the controller is excluded from the automatic antiforgery token validation. |
|||
* `AutoValidateIgnoredHttpMethods`: A list of HTTP Methods to ignore on automatic antiforgery validation. Default value: "GET", "HEAD", "TRACE", "OPTIONS". These HTTP Methods are safe to skip antiforgery validation since they don't change the application state. |
|||
|
|||
If you need to change these options, do it in the `ConfigureServices` method of your [module](Module-Development-Basics.md). |
|||
|
|||
**Example: Configuring the AbpAntiForgeryOptions** |
|||
|
|||
```csharp |
|||
Configure<AbpAntiForgeryOptions>(options => |
|||
{ |
|||
options.TokenCookie.Expiration = TimeSpan.FromDays(365); |
|||
options.AutoValidateIgnoredHttpMethods.Remove("GET"); |
|||
options.AutoValidateFilter = |
|||
type => !type.Namespace.StartsWith("MyProject.MyIgnoredNamespace"); |
|||
}); |
|||
``` |
|||
|
|||
This configuration; |
|||
|
|||
* Sets the antiforgery token expiration time to ~1 year. |
|||
* Enables antiforgery token validation for GET requests too. |
|||
* Ignores the controller types in the specified namespace. |
|||
|
|||
### AntiforgeryOptions |
|||
|
|||
`AntiforgeryOptions` is the standard [options class](Options.md) of the ASP.NET Core. **You can find all the information about this class in its [own documentation](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery)**. |
|||
|
|||
`HeaderName` option is especially important for the ABP Framework point of view. Default value of this value is `RequestVerificationToken` and the clients uses this name while sending the token value in the header. So, if you change this option, you should also arrange your clients to align the change. If you don't have a good reason, leave it as default. |
|||
|
|||
### AbpValidateAntiForgeryToken Attribute |
|||
|
|||
If you disable the automatic validation or want to perform the validation for an endpoint that is not validated by default (for example, an endpoint with HTTP GET Method), you can use the `[AbpValidateAntiForgeryToken]` attribute for a **controller type or method** (action). |
|||
|
|||
**Example: Add `[AbpValidateAntiForgeryToken]` to a HTTP GET method** |
|||
|
|||
```csharp |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.AntiForgery; |
|||
|
|||
namespace MyCompanyName.MyProjectName.Controllers |
|||
{ |
|||
[Route("api/products")] |
|||
public class ProductController : AbpController |
|||
{ |
|||
[HttpGet] |
|||
[AbpValidateAntiForgeryToken] |
|||
public async Task GetAsync() |
|||
{ |
|||
//TODO: ... |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
### Angular UI |
|||
|
|||
Angular supports CSRF Token out of box, but the token header name is `X-XSRF-TOKEN`. Since ABP Framework follows the ASP.NET Core conventions, it changes this value to `RequestVerificationToken` in the core package. |
|||
|
|||
You don't need to make anything unless you need to change the `AntiforgeryOptions.HeaderName` as explained before. If you change it, remember to change the header name for the Angular application too. To do that, add an import declaration for the `HttpClientXsrfModule` into your root module. |
|||
|
|||
**Example: Change the header name to *MyCustomHeaderName*** |
|||
|
|||
```typescript |
|||
@NgModule({ |
|||
// ... |
|||
imports: [ |
|||
//... |
|||
HttpClientXsrfModule.withOptions({ |
|||
cookieName: 'XSRF-TOKEN', |
|||
headerName: 'MyCustomHeaderName' |
|||
}) |
|||
], |
|||
}) |
|||
export class AppModule {} |
|||
``` |
|||
|
|||
**Note:** XSRF-TOKEN is only valid if both frontend application and APIs run on the same domain. Therefore, when you make a request, you should use a relative path. |
|||
|
|||
For example, let's say your APIs is hosted at `https://testdomain.com/ws` |
|||
and your angular application is hosted at `https://testdomain.com/admin` |
|||
|
|||
So if your API request should look like this `https://testdomain.com/ws/api/identity/users` |
|||
|
|||
your `environment.prod.ts` has to be as follows: |
|||
|
|||
```typescript |
|||
export const environment = { |
|||
production: true, |
|||
// .... |
|||
apis: { |
|||
default: { |
|||
url: '/ws', // <- just use the context root here |
|||
// ... |
|||
}, |
|||
}, |
|||
} as Config.Environment; |
|||
``` |
|||
|
|||
Let's talk about why. |
|||
|
|||
First, take a look at [Angular's code](https://github.com/angular/angular/blob/master/packages/common/http/src/xsrf.ts#L81) |
|||
|
|||
It does not intercept any request that starts with `http://` or `https://`. There is a good reason for that. Any cross-site request does not need this token for security. This verification is only valid if the request is made to the same domain from which the web page is served. So, simply put, if you serve everything from a single domain, you just use a relative path. |
|||
@ -0,0 +1,477 @@ |
|||
# Replacing Email Templates and Sending Emails |
|||
|
|||
## Introduction |
|||
|
|||
Hi, in this step by step article, we will send an email by using standard email template and then we will replace the standard email template with our new created template, thanks to [Text Templating System](https://docs.abp.io/en/abp/latest/Text-Templating#replacing-the-existing-templates) and [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). Let's start by explaining what these systems do. |
|||
|
|||
* ABP framework provides a strong and flexible [Text Templating System](https://docs.abp.io/en/abp/latest/Text-Templating). So, we can use the text templating system to create dynamic email contents on a template and a model. |
|||
|
|||
* In this article, we will use `StandardEmailTemplates.Message` as standard email template. Then we will create a new template and replace the standard email template with our new template by using [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). |
|||
|
|||
* The `Virtual File System` makes it possible to manage files that do not physically exist on the file system. That means we can override `StandardEmailTemplates.Message` template by changing it's path with our new template's path. |
|||
|
|||
## Creating the Solution |
|||
|
|||
> ABP Framework offers startup templates to get into the business faster. |
|||
|
|||
In this article, I will create a new startup template and perform the operations on this template. But if you already have a project you don't need to create a new startup template, you can implement the following steps to your existing project. (These steps can be applied to any project. (MVC, Angular etc.)) |
|||
|
|||
> If you have already a project you can skip this section. |
|||
|
|||
Before starting to development, we will create a solution named `TemplateReplace` (or whatever you want). We can create a new startup template by using [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) : |
|||
|
|||
````bash |
|||
abp new TemplateReplace |
|||
```` |
|||
|
|||
Our project boilerplate will be ready after the download is finished. Then, open the solution in the Visual Studio (or your favorite IDE). |
|||
|
|||
Run the `TemplateReplace.DbMigrator` application as below to create the database and seed initial data (which creates the admin user, admin role, permissions etc.). |
|||
|
|||
 |
|||
|
|||
* Right click to `TemplateReplace.DbMigrator` and choose the `Debug`. |
|||
|
|||
 |
|||
|
|||
* After that, click the `Start new instance` option to start the database migrations. |
|||
|
|||
 |
|||
|
|||
Then we can run the `TemplateReplace.Web` project to see our application working. |
|||
|
|||
> _Default login credentials for admin: username is **admin** and password is **1q2w3E\***_ |
|||
|
|||
## Starting the Development |
|||
|
|||
First thing we need to do is, creating a email service to sending emails. ABP Framework provides `IEmailSender` service that is used to send emails. |
|||
|
|||
### Step - 1 |
|||
|
|||
Create an `Emailing` folder in the `TemplateReplace.Domain` project and add a class named `EmailService` inside of it. |
|||
|
|||
```csharp |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Emailing; |
|||
using Volo.Abp.Emailing.Templates; |
|||
using Volo.Abp.TextTemplating; |
|||
|
|||
namespace TemplateReplace.Emailing |
|||
{ |
|||
public class EmailService : ITransientDependency |
|||
{ |
|||
private readonly IEmailSender _emailSender; |
|||
private readonly ITemplateRenderer _templateRenderer; |
|||
|
|||
public EmailService(IEmailSender emailSender, ITemplateRenderer templateRenderer) |
|||
{ |
|||
_emailSender = emailSender; |
|||
_templateRenderer = templateRenderer; |
|||
} |
|||
|
|||
public async Task SendAsync(string targetEmail) |
|||
{ |
|||
var emailBody = await _templateRenderer.RenderAsync( |
|||
StandardEmailTemplates.Message, |
|||
new |
|||
{ |
|||
message = "ABP Framework provides IEmailSender service that is used to send emails." |
|||
} |
|||
); |
|||
|
|||
await _emailSender.SendAsync( |
|||
targetEmail, |
|||
"Subject", |
|||
emailBody |
|||
); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
* To create an email content, we need to inject `ITemplateRenderer` and use the `RenderAsync` method to render a template. |
|||
|
|||
* We've used `StandardEmailTemplates.Message` as standart email template. This provides us a standard and simple message template to send mails. |
|||
|
|||
* The resulting email body should be like shown below: |
|||
|
|||
```html |
|||
<!DOCTYPE html> |
|||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> |
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
</head> |
|||
<body> |
|||
ABP Framework provides IEmailSender service that is used to send emails. |
|||
</body> |
|||
</html> |
|||
``` |
|||
|
|||
### Step - 2 (Configuring Email Settings) |
|||
|
|||
* Now, we need to configure some email settings by following [settings documentation](https://docs.abp.io/en/abp/latest/Settings#setting-values-in-the-application-configuration). For achieve this, open the `appsettings.json` file under `TemplateReplace.Web` and configure your email settings in **settings** section like below. |
|||
|
|||
 |
|||
|
|||
* Here, I used Google's SMTP settings to send emails via Gmail. You can change these setting values by your need. |
|||
|
|||
> **Note:** If you want to use Google's SMTP server settings and send emails via Gmail, you should confirm [this](https://myaccount.google.com/u/0/lesssecureapps). |
|||
|
|||
### Step - 3 |
|||
|
|||
* After that we need to open `TemplateReplaceDomainModule.cs` file and change its contents as below to sending real-time emails. |
|||
|
|||
```csharp |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.DependencyInjection.Extensions; |
|||
using TemplateReplace.MultiTenancy; |
|||
using Volo.Abp.AuditLogging; |
|||
using Volo.Abp.BackgroundJobs; |
|||
using Volo.Abp.Emailing; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.IdentityServer; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.PermissionManagement.Identity; |
|||
using Volo.Abp.PermissionManagement.IdentityServer; |
|||
using Volo.Abp.SettingManagement; |
|||
using Volo.Abp.TenantManagement; |
|||
|
|||
namespace TemplateReplace |
|||
{ |
|||
[DependsOn( |
|||
typeof(TemplateReplaceDomainSharedModule), |
|||
typeof(AbpAuditLoggingDomainModule), |
|||
typeof(AbpBackgroundJobsDomainModule), |
|||
typeof(AbpFeatureManagementDomainModule), |
|||
typeof(AbpIdentityDomainModule), |
|||
typeof(AbpPermissionManagementDomainIdentityModule), |
|||
typeof(AbpIdentityServerDomainModule), |
|||
typeof(AbpPermissionManagementDomainIdentityServerModule), |
|||
typeof(AbpSettingManagementDomainModule), |
|||
typeof(AbpTenantManagementDomainModule), |
|||
typeof(AbpEmailingModule) |
|||
)] |
|||
public class TemplateReplaceDomainModule : AbpModule |
|||
{ |
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var settingManager = context.ServiceProvider.GetService<SettingManager>(); |
|||
//encrypts the password on set and decrypts on get |
|||
settingManager.SetGlobalAsync(EmailSettingNames.Smtp.Password, "your_password"); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpMultiTenancyOptions>(options => |
|||
{ |
|||
options.IsEnabled = MultiTenancyConsts.IsEnabled; |
|||
}); |
|||
|
|||
// #if DEBUG |
|||
// context.Services.Replace(ServiceDescriptor.Singleton<IEmailSender, NullEmailSender>()); |
|||
// #endif |
|||
} |
|||
} |
|||
} |
|||
|
|||
``` |
|||
|
|||
* `NullEmailSender` is a built-in class that implements the `IEmailSender`, but writes email contents to the standard log system, rather than actually sending the emails. This class can be useful especially in development time where you generally don't want to send real emails. Therefore ABP framework defined this by default. But in our case we want to send real emails, so we must remove these lines or we must take it to the comment line. |
|||
|
|||
* `Abp.Mailing.Smtp.Password` must be an encrypted value. Therefore we used `SettingManager` in here to set the password. It internally **encrypts** the values on set and **decrypts** on get. |
|||
|
|||
* After all these steps, whenever we want to send an email, we can do it by using our `EmailService` class. We can inject this class and invoke the `SendAsync` method to sending email where its needed. |
|||
|
|||
After sending the email we should see the template like below. |
|||
|
|||
 |
|||
|
|||
### Step - 4 (Defining New Template) |
|||
|
|||
* So far we've sent mail by using standard email template of ABP. But we may want to replace the email template with the new one. We can achieve this by following the `Text Templating` [documentation](https://docs.abp.io/en/abp/latest/Text-Templating#replacing-the-existing-templates). |
|||
|
|||
* In this article, I will create a email template by using free template generator named **Bee**. You can reach the free templates from [here](https://beefree.io/templates/free/). |
|||
|
|||
* When we find a template for our purpose, we can hover the link and click the **get started** button to edit the template. (I chose a template named "gdpr".) |
|||
|
|||
* Here, you can edit your template as below. (You can delete or add sections, edit texts, and so on.) |
|||
|
|||
 |
|||
|
|||
> **Note:** After editing our template, we need to export it to reach our created template's content. You can see the **export** button top-right of the template editing page. |
|||
|
|||
* After choosing and editing our free template, we can create a new **email template** in our project. For this, create a folder named `Templates` under `Emailing` folder in `TemplateReplace.Domain` and add `EmailTemplate.tpl` file inside of it. And copy-paste the below content or your template's content. |
|||
|
|||
```tpl |
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml"> |
|||
<head> |
|||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/> |
|||
<meta content="width=device-width" name="viewport"/> |
|||
<meta content="IE=edge" http-equiv="X-UA-Compatible"/> |
|||
<style type="text/css"> |
|||
body { |
|||
margin: 0; |
|||
padding: 0; |
|||
} |
|||
table, |
|||
td, |
|||
tr { |
|||
vertical-align: top; |
|||
border-collapse: collapse; |
|||
} |
|||
* { |
|||
line-height: inherit; |
|||
} |
|||
a[x-apple-data-detectors=true] { |
|||
color: inherit !important; |
|||
text-decoration: none !important; |
|||
} |
|||
</style> |
|||
<style id="media-query" type="text/css"> |
|||
@media (max-width: 670px) { |
|||
.block-grid, |
|||
.col { |
|||
min-width: 320px !important; |
|||
max-width: 100% !important; |
|||
display: block !important; |
|||
} |
|||
.block-grid { |
|||
width: 100% !important; |
|||
} |
|||
.col { |
|||
width: 100% !important; |
|||
} |
|||
.col>div { |
|||
margin: 0 auto; |
|||
} |
|||
img.fullwidth, |
|||
img.fullwidthOnMobile { |
|||
max-width: 100% !important; |
|||
} |
|||
.no-stack .col { |
|||
min-width: 0 !important; |
|||
display: table-cell !important; |
|||
} |
|||
.no-stack.two-up .col { |
|||
width: 50% !important; |
|||
} |
|||
.no-stack .col.num2 { |
|||
width: 16.6% !important; |
|||
} |
|||
.no-stack .col.num3 { |
|||
width: 25% !important; |
|||
} |
|||
.no-stack .col.num4 { |
|||
width: 33% !important; |
|||
} |
|||
.no-stack .col.num5 { |
|||
width: 41.6% !important; |
|||
} |
|||
.no-stack .col.num6 { |
|||
width: 50% !important; |
|||
} |
|||
.no-stack .col.num7 { |
|||
width: 58.3% !important; |
|||
} |
|||
.no-stack .col.num8 { |
|||
width: 66.6% !important; |
|||
} |
|||
.no-stack .col.num9 { |
|||
width: 75% !important; |
|||
} |
|||
.no-stack .col.num10 { |
|||
width: 83.3% !important; |
|||
} |
|||
.video-block { |
|||
max-width: none !important; |
|||
} |
|||
.mobile_hide { |
|||
min-height: 0px; |
|||
max-height: 0px; |
|||
max-width: 0px; |
|||
display: none; |
|||
overflow: hidden; |
|||
font-size: 0px; |
|||
} |
|||
.desktop_hide { |
|||
display: block !important; |
|||
max-height: none !important; |
|||
} |
|||
} |
|||
</style> |
|||
</head> |
|||
<body class="clean-body" style="margin: 0; padding: 0; -webkit-text-size-adjust: 100%; background-color: #3d1554;"> |
|||
<table bgcolor="#3d1554" cellpadding="0" cellspacing="0" class="nl-container" role="presentation" style="table-layout: fixed; vertical-align: top; min-width: 320px; border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #3d1554; width: 100%;" valign="top" width="100%"> |
|||
<tbody> |
|||
<tr style="vertical-align: top;" valign="top"> |
|||
<td style="word-break: break-word; vertical-align: top;" valign="top"> |
|||
<div style="background-color:transparent;overflow:hidden"> |
|||
<div class="block-grid" style="min-width: 320px; max-width: 650px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; Margin: 0 auto; width: 100%; background-color: transparent;"> |
|||
<div style="border-collapse: collapse;display: table;width: 100%;background-color:transparent;"> |
|||
<div class="col num12" style="min-width: 320px; max-width: 650px; display: table-cell; vertical-align: top; width: 650px;"> |
|||
<div style="width:100% !important;"> |
|||
<div style="border-top:0px solid transparent; border-left:0px solid transparent; border-bottom:0px solid transparent; border-right:0px solid transparent; padding-top:35px; padding-bottom:0px; padding-right: 0px; padding-left: 0px;"> |
|||
<div align="center" class="img-container center autowidth" style="padding-right: 0px;padding-left: 0px;"></div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div style="background-color:transparent;overflow:hidden"> |
|||
<div class="block-grid" style="min-width: 320px; max-width: 650px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; Margin: 0 auto; width: 100%; background-color: transparent;"> |
|||
<div style="border-collapse: collapse;display: table;width: 100%;background-color:transparent;"> |
|||
<div class="col num12" style="min-width: 320px; max-width: 650px; display: table-cell; vertical-align: top; width: 642px;"> |
|||
<div style="width:100% !important;"> |
|||
<div style="border-top:0px solid transparent; border-left:4px solid #57366E; border-bottom:0px solid transparent; border-right:4px solid #57366E; padding-top:55px; padding-bottom:60px; padding-right: 0px; padding-left: 0px;"> |
|||
<div style="color:#fbd711;font-family:Poppins, Arial, Helvetica, sans-serif;line-height:1.2;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;"> |
|||
<div style="line-height: 1.2; font-size: 12px; color: #fbd711; font-family: Poppins, Arial, Helvetica, sans-serif; mso-line-height-alt: 14px;"> |
|||
<p style="font-size: 14px; line-height: 1.2; word-break: break-word; text-align: center; mso-line-height-alt: 17px; margin: 0;"><strong><span style="font-size: 30px;">ABP Community </span></strong></p> |
|||
</div> |
|||
</div> |
|||
<div style="color:#ffffff;font-family:Poppins, Arial, Helvetica, sans-serif;line-height:1.8;padding-top:10px;padding-right:50px;padding-bottom:10px;padding-left:50px;"> |
|||
<div style="line-height: 1.8; font-size: 12px; color: #ffffff; font-family: Poppins, Arial, Helvetica, sans-serif; mso-line-height-alt: 22px;"> |
|||
<p style="line-height: 1.8; word-break: break-word; font-size: 14px; mso-line-height-alt: 25px; margin: 0;"><span style="font-size: 14px;">Share your experiences with the ABP Framework!</span><br/><span style="font-size: 14px;">ABP is an open source and community driven project. This guide is aims to help anyone wants to contribute to the project.</span></p> |
|||
<p style="line-height: 1.8; word-break: break-word; font-size: 14px; mso-line-height-alt: 25px; margin: 0;"><span style="font-size: 14px;">If you want to write articles or "how to" guides related to the ABP Framework and ASP.NET Core, please submit your article to the community.abp.io web site.</span></p> |
|||
</div> |
|||
</div> |
|||
<div align="center" class="button-container" style="padding-top:12px;padding-right:10px;padding-bottom:12px;padding-left:10px;"> |
|||
<a href="http://www.example.com/" style="-webkit-text-size-adjust: none; text-decoration: none; display: inline-block; color: #000000; background-color: #fbd711; border-radius: 30px; -webkit-border-radius: 30px; -moz-border-radius: 30px; width: auto; width: auto; border-top: 1px solid #fbd711; border-right: 1px solid #fbd711; border-bottom: 1px solid #fbd711; border-left: 1px solid #fbd711; padding-top: 10px; padding-bottom: 10px; font-family: Poppins, Arial, Helvetica, sans-serif; text-align: center; mso-border-alt: none; word-break: keep-all;" target="_blank"><span style="padding-left:45px;padding-right:45px;font-size:18px;display:inline-block;"><span style="font-size: 16px; line-height: 2; word-break: break-word; mso-line-height-alt: 32px;"><span data-mce-style="font-size: 18px; line-height: 36px;" style="font-size: 18px; line-height: 36px;"><strong>Contribute</strong></span></span></span></a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</body> |
|||
</html> |
|||
``` |
|||
|
|||
* Then we need to make the template file as "Embedded Resource". We can do this as below. |
|||
|
|||
* First right click to **EmailTemplate.tpl** and choose `Properties`. |
|||
|
|||
 |
|||
|
|||
* Then be sure about build action is **Embedded resource**. |
|||
|
|||
 |
|||
|
|||
### Step - 4 (Replacing the Email Template) |
|||
|
|||
* To replace the current email template with our new email template, we need to override it. To achieve this, create a class named `EmailTemplateDefinitionProvider` under `Emailing` folder in `TemplateReplace.Domain` and fill it with the below content. |
|||
|
|||
```csharp |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Emailing.Templates; |
|||
using Volo.Abp.TextTemplating; |
|||
|
|||
namespace TemplateReplace.Emailing |
|||
{ |
|||
public class EmailTemplateDefinitionProvider : TemplateDefinitionProvider, ITransientDependency |
|||
{ |
|||
public override void Define(ITemplateDefinitionContext context) |
|||
{ |
|||
var emailLayoutTemplate = context.GetOrNull(StandardEmailTemplates.Message); |
|||
|
|||
emailLayoutTemplate |
|||
.WithVirtualFilePath( |
|||
"/Emailing/Templates/EmailTemplate.tpl", |
|||
isInlineLocalized: true |
|||
); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
* In here we've created a template definition provider class that gets the email layout template and change the virtual file path for the template. |
|||
|
|||
* This approach allows us to locate templates in any folder instead of the folder defined by the depended module. For more detail, check the [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). |
|||
|
|||
### Step - 5 |
|||
|
|||
* Lastly, we need to configure the [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). To do this open your `TemplateReplaceDomainModule.cs` in `TemplateReplace.Domain` and update the content as below. |
|||
|
|||
```csharp |
|||
using TemplateReplace.MultiTenancy; |
|||
using Volo.Abp.AuditLogging; |
|||
using Volo.Abp.BackgroundJobs; |
|||
using Volo.Abp.Emailing; |
|||
using Volo.Abp.FeatureManagement; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.IdentityServer; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.PermissionManagement.Identity; |
|||
using Volo.Abp.PermissionManagement.IdentityServer; |
|||
using Volo.Abp.SettingManagement; |
|||
using Volo.Abp.TenantManagement; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace TemplateReplace |
|||
{ |
|||
[DependsOn( |
|||
typeof(TemplateReplaceDomainSharedModule), |
|||
typeof(AbpAuditLoggingDomainModule), |
|||
typeof(AbpBackgroundJobsDomainModule), |
|||
typeof(AbpFeatureManagementDomainModule), |
|||
typeof(AbpIdentityDomainModule), |
|||
typeof(AbpPermissionManagementDomainIdentityModule), |
|||
typeof(AbpIdentityServerDomainModule), |
|||
typeof(AbpPermissionManagementDomainIdentityServerModule), |
|||
typeof(AbpSettingManagementDomainModule), |
|||
typeof(AbpTenantManagementDomainModule), |
|||
typeof(AbpEmailingModule) |
|||
)] |
|||
public class TemplateReplaceDomainModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpMultiTenancyOptions>(options => |
|||
{ |
|||
options.IsEnabled = MultiTenancyConsts.IsEnabled; |
|||
}); |
|||
|
|||
//Add this configuration |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<TemplateReplaceDomainModule>(); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
``` |
|||
|
|||
* And now when we send a new email, we should see our newly defined template as the message like below. |
|||
|
|||
 |
|||
|
|||
## Text Template Management |
|||
|
|||
* Generally, more than one e-mail is required in applications. We create email templates for **"password changes"** or **"welcome"** etc in our applications. In such cases, it is necessary to create different templates for each mail. ABP Commercial allows us to perform these operations on UI in a simple way. Text Template Management provides UI to easily create and manage email templates. |
|||
|
|||
 |
|||
|
|||
* ABP Commercial's [Text Template Management](https://commercial.abp.io/modules/Volo.TextTemplateManagement) module is really fascinating. It makes it super easy to stores and edits template contents. We can list all templates on a page, editing them, localizing them, and so on. |
|||
|
|||
 |
|||
|
|||
* ABP Commercial's text template management module, allows us to modify a template through the UI. |
|||
|
|||
* I highly recommend you to [check it out](https://commercial.abp.io/modules/Volo.TextTemplateManagement). |
|||
|
|||
## References |
|||
|
|||
* [Text Templating](https://docs.abp.io/en/abp/latest/Text-Templating) |
|||
* [Emailing](https://docs.abp.io/en/abp/latest/Emailing) |
|||
* [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System) |
|||
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 91 KiB |
@ -0,0 +1,160 @@ |
|||
# How to Add Custom Properties to the User Entity |
|||
|
|||
## Introduction |
|||
|
|||
In this step-by-step article, I will explain how you can customize the user entity class, which is available in every web application you create using the ABP framework, according to your needs. When you read this article, you will learn how to override the services of built-in modules, extend the entities, extend data transfer objects and customize the user interface in the applications you develop using the ABP framework. |
|||
|
|||
You can see the screenshots below which we will reach at the end of the article. |
|||
|
|||
 |
|||
|
|||
 |
|||
|
|||
## Preparing the Project |
|||
|
|||
### Startup template and the initial run |
|||
|
|||
Abp Framework offers startup templates to get into the work faster. We can create a new startup template using Abp CLI: |
|||
|
|||
`abp new CustomizeUserDemo` |
|||
|
|||
> In this article, I will go through the MVC application, but it will work also in the [Angular](https://docs.abp.io/en/abp/latest/Getting-Started?UI=NG&DB=EF&Tiered=No) application. |
|||
|
|||
After the download is finished, we can run **CustomizeUserDemo.DbMigrator** project to create the database migrations and seed the initial data (admin user, role, etc). Then we can run `CustomizeUserDemo.Web` to see that our application is working. |
|||
|
|||
> Default admin username is **admin** and password is **1q2w3E\*** |
|||
|
|||
 |
|||
|
|||
In this article, we will go through a scenario together and find the solutions to our questions through this scenario. However, since the scenario is not a real-life scenario, it may be strange, please don't get too about this issue :) |
|||
|
|||
## Step-1 |
|||
|
|||
Add two new properties to the `AppUser` in the Users folder of the **CustomizeUserDemo.Domain** project as follows: |
|||
|
|||
```csharp |
|||
public string Title { get; protected set; } |
|||
|
|||
public int Reputation { get; protected set; } |
|||
``` |
|||
|
|||
## Step-2 |
|||
|
|||
Create the Users folder in the **CustomizeUserDemo.Domain.Shared** project, create the class `UserConsts` inside the folder and update the class you created as below: |
|||
|
|||
```csharp |
|||
public static class UserConsts |
|||
{ |
|||
public const string TitlePropertyName = "Title"; |
|||
|
|||
public const string ReputationPropertyName = "Reputation"; |
|||
|
|||
public const int MaxTitleLength = 64; |
|||
|
|||
public const double MaxReputationValue = 1_000; |
|||
|
|||
public const double MinReputationValue = 1; |
|||
} |
|||
``` |
|||
|
|||
## Step-3 |
|||
|
|||
Update the `CustomizeUserDemoEfCoreEntityExtensionMappings` class in the **CustomizeUserDemo.EntityFramework** project in the EntityFrameworkCore folder as below: |
|||
|
|||
```csharp |
|||
public static class CustomizeUserDemoEfCoreEntityExtensionMappings |
|||
{ |
|||
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); |
|||
|
|||
public static void Configure() |
|||
{ |
|||
CustomizeUserDemoGlobalFeatureConfigurator.Configure(); |
|||
CustomizeUserDemoModuleExtensionConfigurator.Configure(); |
|||
|
|||
OneTimeRunner.Run(() => |
|||
{ |
|||
ObjectExtensionManager.Instance |
|||
.MapEfCoreProperty<IdentityUser, string>( |
|||
nameof(AppUser.Title), |
|||
(entityBuilder, propertyBuilder) => |
|||
{ |
|||
propertyBuilder.IsRequired(); |
|||
propertyBuilder.HasMaxLength(UserConsts.MaxTitleLength); |
|||
} |
|||
).MapEfCoreProperty<IdentityUser, int>( |
|||
nameof(AppUser.Reputation), |
|||
(entityBuilder, propertyBuilder) => |
|||
{ |
|||
propertyBuilder.HasDefaultValue(UserConsts.MinReputationValue); |
|||
} |
|||
); |
|||
}); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
This class can be used to map these extra properties to table fields in the database. Please read [this](https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities) article to improve your understanding of what we are doing. |
|||
|
|||
So far, we have added our extra features to the `User` entity and matched these features with the `ef core`. |
|||
|
|||
Now we need to add migration to see what has changed in our database. This for, open the Package Manager Console (PMC) under the menu Tools > NuGet Package Manager. |
|||
|
|||
 |
|||
|
|||
Select the **CustomizeUserDemo.EntityFramework.DbMigrations** as the **default project** and execute the following command: |
|||
|
|||
```bash |
|||
Add-Migration "Updated-User-Entity" |
|||
``` |
|||
|
|||
 |
|||
|
|||
This will create a new migration class inside the `Migrations` folder of the **CustomizeUserDemo.EntityFrameworkCore.DbMigrations** project. |
|||
|
|||
> If you are using another IDE than the Visual Studio, you can use `dotnet-ef` tool as [documented here](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli#create-a-migration). |
|||
|
|||
Finally, run the **CustomizeUserDemo.DbMigrator** project to update the database. |
|||
|
|||
When we updated the database, you can see that the `Title` and `Reputation` columns are added to the `Users` table. |
|||
|
|||
 |
|||
|
|||
## Step-4 |
|||
Open the `CustomizeUserDemoModuleExtensionConfigurator` in the **CustomizeUserDemo.Domain.Shared** project, and change the contents of the `ConfigureExtraProperties` method as shown below: |
|||
```csharp |
|||
private static void ConfigureExtraProperties() |
|||
{ |
|||
ObjectExtensionManager.Instance.Modules().ConfigureIdentity(identity => |
|||
{ |
|||
identity.ConfigureUser(user => |
|||
{ |
|||
user.AddOrUpdateProperty<string>( |
|||
UserConsts.TitlePropertyName, |
|||
options => |
|||
{ |
|||
options.Attributes.Add(new RequiredAttribute()); |
|||
options.Attributes.Add( |
|||
new StringLengthAttribute(UserConsts.MaxTitleLength) |
|||
); |
|||
} |
|||
); |
|||
user.AddOrUpdateProperty<int>( |
|||
UserConsts.ReputationPropertyName, |
|||
options => |
|||
{ |
|||
options.DefaultValue = UserConsts.MinReputationValue; |
|||
options.Attributes.Add( |
|||
new RangeAttribute(UserConsts.MinReputationValue, UserConsts.MaxReputationValue) |
|||
); |
|||
} |
|||
); |
|||
}); |
|||
}); |
|||
} |
|||
``` |
|||
|
|||
That's it. Now let's run the application and look at the Identity user page. You can also try to edit and recreate a record if you want, it will work even though we haven't done anything extra. Here is the magic code behind ABP framework. |
|||
|
|||
If there is a situation you want to add, you can click the contribute button or make a comment. Also, if you like the article, don't forget to share it :) |
|||
|
|||
Happy coding :) |
|||
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 193 KiB |
@ -0,0 +1,46 @@ |
|||
# How to add a new language to your ABP project? |
|||
|
|||
Adding a new language to your ABP project is pretty simple. Let's add the German language to our ABP project: |
|||
|
|||
|
|||
|
|||
1. Go to your solution's root folder and write the following CLI command. This command will generate an empty translation file from English. |
|||
```bash |
|||
abp translate -c de-DE |
|||
``` |
|||
|
|||
Check out for [the complete supported culture codes](https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes). |
|||
(For internal development `D:\Github\abp` and `D:\Github\volo\abp`) |
|||
|
|||
2. Fill the `target` fields in your target language. |
|||
|
|||
 |
|||
|
|||
3. Copy `abp-translation.json` your solution's root folder (Do not change the filename!) |
|||
|
|||
4. Run the following command. This command will create the necessary `json` files. |
|||
```bash |
|||
abp translate --apply |
|||
``` |
|||
|
|||
5. Open your solution and add the new language to the language list. To do this; |
|||
|
|||
* open `MyProjectNameDomainModule.cs` and in `ConfigureServices` you'll find `Configure<AbpLocalizationOptions>`. If you have `HttpApi.Host` project then you need to add this in `MyProjectNameHttpApiHostModule.cs` |
|||
|
|||
``` |
|||
options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de")); |
|||
``` |
|||
|
|||
 |
|||
|
|||
The last parameter is the flag icon. You can find the list of flag icons on https://flagicons.lipis.dev/ |
|||
|
|||
6. The last step is running the DbMigrator project. It will seed the database for the new language. |
|||
 |
|||
|
|||
|
|||
|
|||
Close the IIS Express / Kestrel to invalidate the language cache and run the project. You will see the new language on your website. |
|||
|
|||
 |
|||
|
|||
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,936 @@ |
|||
# Creating an Event Organizer Application with the ABP Framework & Blazor UI. |
|||
|
|||
## Introduction |
|||
|
|||
In this article, we will create an example application that is a simple **meeting/event organizer**: People create events and other people registers to the event. |
|||
|
|||
The application has been developed with **Blazor** as the UI framework and **MongoDB** as the database provider. |
|||
|
|||
> This tutorial is based on my notes that I'd created to implement this application in a workshop. It shows the necessary steps to build the application rather than detailed explanations. |
|||
|
|||
### Source Code |
|||
|
|||
Source code of the completed application is [available on GitHub](https://github.com/abpframework/abp-samples/tree/master/EventOrganizer). |
|||
|
|||
### Screenshots |
|||
|
|||
Here, the pages of the final application. |
|||
|
|||
**Home Page - Event List** |
|||
|
|||
 |
|||
|
|||
**Creating a new Event** |
|||
|
|||
 |
|||
|
|||
**Event Detail Page** |
|||
|
|||
 |
|||
|
|||
## Requirements |
|||
|
|||
The following tools are needed to be able to run the solution. |
|||
|
|||
* .NET 5.0 SDK |
|||
* Visual Studio 2019 16.8.0+ or another compatible IDE |
|||
* MongoDB Server (with MongoDB Compass) |
|||
|
|||
## Development |
|||
|
|||
### Creating a new Application |
|||
|
|||
* Use the following ABP CLI command: |
|||
|
|||
````bash |
|||
abp new EventOrganizer -u blazor -d mongodb |
|||
```` |
|||
|
|||
### Open & Run the Application |
|||
|
|||
* Open the solution in Visual Studio (or your favorite IDE). |
|||
* Run the `EventOrganizer.DbMigrator` application to seed the initial data. |
|||
* Run the `EventOrganizer.HttpApi.Host` application that starts the server side. |
|||
* Run the `EventOrganizer.Blazor` application to start the UI. |
|||
|
|||
### Apply the Custom Styles |
|||
|
|||
* Add styles to `wwwroot/main.css`: |
|||
|
|||
````css |
|||
body.abp-application-layout { |
|||
background-color: #222 !important; |
|||
font-size: 18px; |
|||
} |
|||
nav#main-navbar.bg-dark { |
|||
background-color: #222 !important; |
|||
box-shadow: none !important; |
|||
} |
|||
.event-pic { |
|||
width: 100%; |
|||
border-radius: 12px; |
|||
box-shadow: 5px 5px 0px 0px rgba(0,0,0,.5); |
|||
margin-bottom: 10px; |
|||
} |
|||
.event-link:hover, .event-link:hover *{ |
|||
text-decoration: none; |
|||
} |
|||
.event-link:hover .event-pic { |
|||
box-shadow: 5px 5px 0px 0px #ffd800; |
|||
} |
|||
.event-form { |
|||
background-color: #333 !important; |
|||
box-shadow: 5px 5px 0px 0px rgba(0,0,0,.5); |
|||
border-radius: 12px; |
|||
} |
|||
.table { |
|||
background: #fff; |
|||
border-radius: 12px; |
|||
box-shadow: 5px 5px 0px 0px rgba(0,0,0,.5); |
|||
} |
|||
.table th{ |
|||
border: 0 !important; |
|||
} |
|||
.modal { |
|||
color: #333; |
|||
} |
|||
.page-item:first-child .page-link { |
|||
margin-left: 0; |
|||
border-top-left-radius: 12px; |
|||
border-bottom-left-radius: 12px; |
|||
} |
|||
.page-item:last-child .page-link { |
|||
border-top-right-radius: 12px; |
|||
border-bottom-right-radius: 12px; |
|||
} |
|||
.btn { |
|||
border-radius: 8px; |
|||
} |
|||
.att-list { |
|||
list-style: none; |
|||
padding: 0; |
|||
} |
|||
.att-list li { |
|||
padding: 4px 0 0 0; |
|||
} |
|||
```` |
|||
|
|||
* `wwwroot/index.html`: Remove `bg-light` class from the `body` tag and add `bg-dark text-light`. |
|||
|
|||
### Domain Layer |
|||
|
|||
* Add the following `Event` aggregate (with `EventAttendee`) to the solution: |
|||
|
|||
**Event** |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.Domain.Entities.Auditing; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public class Event : FullAuditedAggregateRoot<Guid> |
|||
{ |
|||
public string Title { get; set; } |
|||
|
|||
public string Description { get; set; } |
|||
|
|||
public bool IsFree { get; set; } |
|||
|
|||
public DateTime StartTime { get; set; } |
|||
|
|||
public ICollection<EventAttendee> Attendees { get; set; } |
|||
|
|||
public Event() |
|||
{ |
|||
Attendees = new List<EventAttendee>(); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
**EventAttendee** |
|||
|
|||
```csharp |
|||
using System; |
|||
using Volo.Abp.Auditing; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public class EventAttendee : IHasCreationTime |
|||
{ |
|||
public Guid UserId { get; set; } |
|||
|
|||
public DateTime CreationTime { get; set; } |
|||
} |
|||
} |
|||
``` |
|||
|
|||
### MongoDB Mapping |
|||
|
|||
* Add the following property to the `EventOrganizerMongoDbContext`: |
|||
|
|||
````csharp |
|||
public IMongoCollection<Event> Events => Collection<Event>(); |
|||
```` |
|||
|
|||
### Clean Index.razor & Add the Header & "Create Event" button |
|||
|
|||
* Clean the `Index.razor` file. |
|||
* Replace the content with the following code: |
|||
|
|||
````html |
|||
@page "/" |
|||
@inherits EventOrganizerComponentBase |
|||
<Row Class="mb-4"> |
|||
<Column Class="text-left"> |
|||
<h1>Upcoming Events</h1> |
|||
</Column> |
|||
<Column Class="text-right"> |
|||
@if (CurrentUser.IsAuthenticated) |
|||
{ |
|||
<a class="btn btn-primary" href="/create-event"> |
|||
<i class="fa fa-plus"></i> @L["CreateEvent"] |
|||
</a> |
|||
} |
|||
</Column> |
|||
</Row> |
|||
```` |
|||
|
|||
* Open `Localization/EventOrganizer/en.json` in the `EventOrganizer.Domain.Shared` project and add the following entry: |
|||
|
|||
````json |
|||
"CreateEvent": "Create a new event!" |
|||
```` |
|||
|
|||
The Result (run the `EventOrganizer.Blazor` application to see): |
|||
|
|||
 |
|||
|
|||
### Event Creation |
|||
|
|||
* Create the Initial `IEventAppService` with the `CreateAsync` method: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public interface IEventAppService : IApplicationService |
|||
{ |
|||
Task<Guid> CreateAsync(EventCreationDto input); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Add `EventCreationDto` class: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public class EventCreationDto |
|||
{ |
|||
[Required] |
|||
[StringLength(100)] |
|||
public string Title { get; set; } |
|||
|
|||
[Required] |
|||
[StringLength(2000)] |
|||
public string Description { get; set; } |
|||
|
|||
public bool IsFree { get; set; } |
|||
|
|||
public DateTime StartTime { get; set; } |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Implement the `EventAppService`: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Volo.Abp.Domain.Repositories; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public class EventAppService : EventOrganizerAppService, IEventAppService |
|||
{ |
|||
private readonly IRepository<Event, Guid> _eventRepository; |
|||
|
|||
public EventAppService(IRepository<Event, Guid> eventRepository) |
|||
{ |
|||
_eventRepository = eventRepository; |
|||
} |
|||
|
|||
[Authorize] |
|||
public async Task<Guid> CreateAsync(EventCreationDto input) |
|||
{ |
|||
var eventEntity = ObjectMapper.Map<EventCreationDto, Event>(input); |
|||
await _eventRepository.InsertAsync(eventEntity); |
|||
return eventEntity.Id; |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Add AutoMapper mapping to the `EventOrganizerApplicationAutoMapperProfile` class: |
|||
|
|||
````csharp |
|||
using AutoMapper; |
|||
using EventOrganizer.Events; |
|||
|
|||
namespace EventOrganizer |
|||
{ |
|||
public class EventOrganizerApplicationAutoMapperProfile : Profile |
|||
{ |
|||
public EventOrganizerApplicationAutoMapperProfile() |
|||
{ |
|||
CreateMap<EventCreationDto, Event>(); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
This will automatically create the HTTP (REST) API for the application service (run the `EventOrganizer.HttpApi.Host` application to see it on the Swagger UI): |
|||
|
|||
 |
|||
|
|||
* Create the `CreateEvent.razor` file: |
|||
|
|||
````csharp |
|||
@page "/create-event" |
|||
@inherits EventOrganizerComponentBase |
|||
<Heading Size="HeadingSize.Is3" Margin="Margin.Is5.FromTop.Is4.FromBottom" Class="text-center">Create Event</Heading> |
|||
<Row> |
|||
<Column ColumnSize="ColumnSize.Is6.Is3.WithOffset"> |
|||
<div class="p-lg-5 p-md-3 event-form"> |
|||
<EditForm Model="@Event" OnValidSubmit="Create"> |
|||
<Field> |
|||
<FieldLabel>@L["Title"]</FieldLabel> |
|||
<TextEdit @bind-Text="@Event.Title" /> |
|||
</Field> |
|||
<Field> |
|||
<FieldLabel>@L["Description"]</FieldLabel> |
|||
<MemoEdit @bind-Text="@Event.Description" /> |
|||
</Field> |
|||
<Field> |
|||
<Check TValue="bool" @bind-Checked="@Event.IsFree">@L["Free"]</Check> |
|||
</Field> |
|||
<Field> |
|||
<FieldLabel>@L["StartTime"]</FieldLabel> |
|||
<DateEdit TValue="DateTime" @bind-Date="@Event.StartTime" /> |
|||
</Field> |
|||
<Button Type="@ButtonType.Submit" Block="true" Color="@Color.Primary" Size="Size.Large">@L["Save"]</Button> |
|||
</EditForm> |
|||
</div> |
|||
</Column> |
|||
</Row> |
|||
```` |
|||
|
|||
* Create a partial `CreateEvent` class in the same folder, with the `CreateEvent.razor.cs` as the file name: |
|||
|
|||
````csharp |
|||
using System.Threading.Tasks; |
|||
using EventOrganizer.Events; |
|||
using Microsoft.AspNetCore.Components; |
|||
|
|||
namespace EventOrganizer.Blazor.Pages |
|||
{ |
|||
public partial class CreateEvent |
|||
{ |
|||
private EventCreationDto Event { get; set; } = new EventCreationDto(); |
|||
|
|||
private readonly IEventAppService _eventAppService; |
|||
private readonly NavigationManager _navigationManager; |
|||
|
|||
public CreateEvent( |
|||
IEventAppService eventAppService, |
|||
NavigationManager navigationManager) |
|||
{ |
|||
_eventAppService = eventAppService; |
|||
_navigationManager = navigationManager; |
|||
} |
|||
|
|||
private async Task Create() |
|||
{ |
|||
var eventId = await _eventAppService.CreateAsync(Event); |
|||
_navigationManager.NavigateTo("/events/" + eventId); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
The final UI is (run the `EventOrganizer.Blazor` application and click to the "Create Event" button): |
|||
|
|||
 |
|||
|
|||
### Upcoming Events (Home Page) |
|||
|
|||
* Open the `IEventAppService` and add a `GetUpcomingAsync` method to get the list of upcoming events: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public interface IEventAppService : IApplicationService |
|||
{ |
|||
Task<Guid> CreateAsync(EventCreationDto input); |
|||
|
|||
Task<List<EventDto>> GetUpcomingAsync(); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Add a `EventDto` class: |
|||
|
|||
````csharp |
|||
using System; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public class EventDto : EntityDto<Guid> |
|||
{ |
|||
public string Title { get; set; } |
|||
|
|||
public string Description { get; set; } |
|||
|
|||
public bool IsFree { get; set; } |
|||
|
|||
public DateTime StartTime { get; set; } |
|||
|
|||
public int AttendeesCount { get; set; } |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Implement the `GetUpcomingAsync` in the `EventAppService` class: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Volo.Abp.Domain.Repositories; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public class EventAppService : EventOrganizerAppService, IEventAppService |
|||
{ |
|||
private readonly IRepository<Event, Guid> _eventRepository; |
|||
|
|||
public EventAppService(IRepository<Event, Guid> eventRepository) |
|||
{ |
|||
_eventRepository = eventRepository; |
|||
} |
|||
|
|||
[Authorize] |
|||
public async Task<Guid> CreateAsync(EventCreationDto input) |
|||
{ |
|||
var eventEntity = ObjectMapper.Map<EventCreationDto, Event>(input); |
|||
await _eventRepository.InsertAsync(eventEntity); |
|||
return eventEntity.Id; |
|||
} |
|||
|
|||
public async Task<List<EventDto>> GetUpcomingAsync() |
|||
{ |
|||
var events = await AsyncExecuter.ToListAsync( |
|||
_eventRepository |
|||
.Where(x => x.StartTime > Clock.Now) |
|||
.OrderBy(x => x.StartTime) |
|||
); |
|||
|
|||
return ObjectMapper.Map<List<Event>, List<EventDto>>(events); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Add the following line into the `EventOrganizerApplicationAutoMapperProfile` constructor: |
|||
|
|||
````csharp |
|||
CreateMap<Event, EventDto>(); |
|||
```` |
|||
|
|||
Run the `EventOrganizer.HttpApi.Host` application to see the new `upcoming` endpoint on the Swagger UI: |
|||
|
|||
 |
|||
|
|||
* Change the `Pages/Index.razor.cs` content in the `EventOrganizer.Blazor` project as shown below: |
|||
|
|||
```csharp |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EventOrganizer.Events; |
|||
|
|||
namespace EventOrganizer.Blazor.Pages |
|||
{ |
|||
public partial class Index |
|||
{ |
|||
private List<EventDto> UpcomingEvents { get; set; } = new List<EventDto>(); |
|||
|
|||
private readonly IEventAppService _eventAppService; |
|||
|
|||
public Index(IEventAppService eventAppService) |
|||
{ |
|||
_eventAppService = eventAppService; |
|||
} |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
UpcomingEvents = await _eventAppService.GetUpcomingAsync(); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
* Change the `Pages/Index.razor` content in the `EventOrganizer.Blazor` project as shown below: |
|||
|
|||
````html |
|||
@page "/" |
|||
@inherits EventOrganizerComponentBase |
|||
<Row Class="mb-4"> |
|||
<Column Class="text-left"> |
|||
<h1>Upcoming Events</h1> |
|||
</Column> |
|||
<Column Class="text-right"> |
|||
@if (CurrentUser.IsAuthenticated) |
|||
{ |
|||
<a class="btn btn-primary" href="/create-event"> |
|||
<i class="fa fa-plus"></i> @L["CreateEvent"] |
|||
</a> |
|||
} |
|||
</Column> |
|||
</Row> |
|||
<Row> |
|||
@foreach (var upcomingEvent in UpcomingEvents) |
|||
{ |
|||
<Column Class="col-12 col-lg-4 col-md-6"> |
|||
<a class="mb-5 position-relative d-block event-link" href="/events/@upcomingEvent.Id"> |
|||
<div class="position-absolute text-right w-100 px-3 py-2" style="left: 0; top: 2px;"> |
|||
@if (upcomingEvent.IsFree) |
|||
{ |
|||
<Badge Color="Color.Success" Class="mr-1">FREE</Badge> |
|||
} |
|||
<span class="badge badge-warning font-weight-normal"> |
|||
<i class="fas fa-user-friends"></i> |
|||
<span class="font-weight-bold">@upcomingEvent.AttendeesCount</span> |
|||
</span> |
|||
</div> |
|||
<img src="https://picsum.photos/seed/@upcomingEvent.Id/400/300" class="event-pic"/> |
|||
<div class="px-3 py-1"> |
|||
<small class="font-weight-bold text-warning my-2 d-block text-uppercase">@upcomingEvent.StartTime.ToLongDateString()</small> |
|||
<p class="h4 text-light d-block mb-2">@upcomingEvent.Title</p> |
|||
<p class="text-light" style="opacity: .65;">@upcomingEvent.Description.TruncateWithPostfix(150)</p> |
|||
</div> |
|||
</a> |
|||
</Column> |
|||
} |
|||
</Row> |
|||
```` |
|||
|
|||
The new home page is shown below: |
|||
|
|||
 |
|||
|
|||
### Event Detail Page |
|||
|
|||
* Add `GetAsync`, `RegisterAsync`, `UnregisterAsync` and `DeleteAsync` methods to the `IEventAppService`: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public interface IEventAppService : IApplicationService |
|||
{ |
|||
Task<Guid> CreateAsync(EventCreationDto input); |
|||
|
|||
Task<List<EventDto>> GetUpcomingAsync(); |
|||
|
|||
Task<EventDetailDto> GetAsync(Guid id); |
|||
|
|||
Task RegisterAsync(Guid id); |
|||
|
|||
Task UnregisterAsync(Guid id); |
|||
|
|||
Task DeleteAsync(Guid id); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Add `EventDetailDto` class: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public class EventDetailDto : CreationAuditedEntityDto<Guid> |
|||
{ |
|||
public string Title { get; set; } |
|||
|
|||
public string Description { get; set; } |
|||
|
|||
public bool IsFree { get; set; } |
|||
|
|||
public DateTime StartTime { get; set; } |
|||
|
|||
public List<EventAttendeeDto> Attendees { get; set; } |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Add `EventAttendeeDto` class: |
|||
|
|||
````csharp |
|||
using System; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public class EventAttendeeDto |
|||
{ |
|||
public Guid UserId { get; set; } |
|||
|
|||
public string UserName { get; set; } |
|||
|
|||
public DateTime CreationTime { get; set; } |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Implement the new methods in the `EventAppService`: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EventOrganizer.Users; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Users; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
public class EventAppService : EventOrganizerAppService, IEventAppService |
|||
{ |
|||
private readonly IRepository<Event, Guid> _eventRepository; |
|||
private readonly IRepository<AppUser, Guid> _userRepository; |
|||
|
|||
public EventAppService(IRepository<Event, Guid> eventRepository, IRepository<AppUser, Guid> userRepository) |
|||
{ |
|||
_eventRepository = eventRepository; |
|||
_userRepository = userRepository; |
|||
} |
|||
|
|||
[Authorize] |
|||
public async Task<Guid> CreateAsync(EventCreationDto input) |
|||
{ |
|||
var eventEntity = ObjectMapper.Map<EventCreationDto, Event>(input); |
|||
await _eventRepository.InsertAsync(eventEntity); |
|||
return eventEntity.Id; |
|||
} |
|||
|
|||
public async Task<List<EventDto>> GetUpcomingAsync() |
|||
{ |
|||
var events = await AsyncExecuter.ToListAsync( |
|||
_eventRepository |
|||
.Where(x => x.StartTime > Clock.Now) |
|||
.OrderBy(x => x.StartTime) |
|||
); |
|||
|
|||
return ObjectMapper.Map<List<Event>, List<EventDto>>(events); |
|||
} |
|||
|
|||
public async Task<EventDetailDto> GetAsync(Guid id) |
|||
{ |
|||
var @event = await _eventRepository.GetAsync(id); |
|||
var attendeeIds = @event.Attendees.Select(a => a.UserId).ToList(); |
|||
var attendees = (await AsyncExecuter.ToListAsync(_userRepository.Where(u => attendeeIds.Contains(u.Id)))) |
|||
.ToDictionary(x => x.Id); |
|||
|
|||
var result = ObjectMapper.Map<Event, EventDetailDto>(@event); |
|||
|
|||
foreach (var attendeeDto in result.Attendees) |
|||
{ |
|||
attendeeDto.UserName = attendees[attendeeDto.UserId].UserName; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
[Authorize] |
|||
public async Task RegisterAsync(Guid id) |
|||
{ |
|||
var @event = await _eventRepository.GetAsync(id); |
|||
if (@event.Attendees.Any(a => a.UserId == CurrentUser.Id)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
@event.Attendees.Add(new EventAttendee {UserId = CurrentUser.GetId(), CreationTime = Clock.Now}); |
|||
await _eventRepository.UpdateAsync(@event); |
|||
} |
|||
|
|||
[Authorize] |
|||
public async Task UnregisterAsync(Guid id) |
|||
{ |
|||
var @event = await _eventRepository.GetAsync(id); |
|||
var removedItems = @event.Attendees.RemoveAll(x => x.UserId == CurrentUser.Id); |
|||
if (removedItems.Any()) |
|||
{ |
|||
await _eventRepository.UpdateAsync(@event); |
|||
} |
|||
} |
|||
|
|||
[Authorize] |
|||
public async Task DeleteAsync(Guid id) |
|||
{ |
|||
var @event = await _eventRepository.GetAsync(id); |
|||
|
|||
if (CurrentUser.Id != @event.CreatorId) |
|||
{ |
|||
throw new UserFriendlyException("You don't have the necessary permission to delete this event!"); |
|||
} |
|||
|
|||
await _eventRepository.DeleteAsync(id); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Add the following mappings into the `EventOrganizerApplicationAutoMapperProfile`: |
|||
|
|||
````csharp |
|||
CreateMap<Event, EventDetailDto>(); |
|||
CreateMap<EventAttendee, EventAttendeeDto>(); |
|||
```` |
|||
|
|||
Run the `EventOrganizer.HttpApi.Host` application to see the complete Event HTTP API in the Swagger UI: |
|||
|
|||
 |
|||
|
|||
* Create `EventDetail.razor` component with the following content: |
|||
|
|||
````html |
|||
@page "/events/{id}" |
|||
@inherits EventOrganizerComponentBase |
|||
@if (Event != null) |
|||
{ |
|||
<Row Class="mb-4"> |
|||
<Column Class="text-left"> |
|||
<h1>@Event.Title</h1> |
|||
</Column> |
|||
<Column Class="text-right pt-2"> |
|||
<a href="/" Class="btn btn-dark"><i class="fa fa-arrow-left"></i> Back</a> |
|||
@if (CurrentUser.IsAuthenticated && CurrentUser.Id == Event.CreatorId) |
|||
{ |
|||
<Button Color="Color.Danger" Clicked="Delete" Class="ml-1">Delete</Button> |
|||
} |
|||
</Column> |
|||
</Row> |
|||
<Row> |
|||
<Column Class="col-12 col-md-8"> |
|||
<div class="position-relative"> |
|||
<div class="position-absolute text-right w-100 px-3 py-2" style="left: 0; top: 2px;"> |
|||
@if (Event.IsFree) |
|||
{ |
|||
<Badge Color="Color.Success" Class="mr-1">FREE</Badge> |
|||
} |
|||
<span class="badge badge-warning font-weight-normal"> |
|||
<i class="fas fa-user-friends"></i> |
|||
<span class="font-weight-bold">@Event.Attendees.Count</span> |
|||
</span> |
|||
</div> |
|||
<img src="https://picsum.photos/seed/@Event.Id/800/600" class="event-pic" /> |
|||
<small class="font-weight-bold text-warning my-2 d-block text-uppercase">Start time: @Event.StartTime.ToLongDateString()</small> |
|||
<p style="opacity: .65;">@Event.Description</p> |
|||
</div> |
|||
</Column> |
|||
<Column Class="col-12 col-md-4"> |
|||
<div class="p-4 event-form"> |
|||
@if (CurrentUser.IsAuthenticated) |
|||
{ |
|||
<div> |
|||
@if (!IsRegistered) |
|||
{ |
|||
<Button Color="Color.Primary" Clicked="Register" Class="btn-block btn-lg">Register now!</Button> |
|||
} |
|||
else |
|||
{ |
|||
<p>You are registered in this event</p> |
|||
<Button Color="Color.Secondary" Clicked="UnRegister" Class="btn-block">Cancel registration!</Button> |
|||
} |
|||
</div> |
|||
} |
|||
else |
|||
{ |
|||
<a class="btn btn-primary" href="/authentication/login"> |
|||
<i class="fa fa-sign-in-alt"></i> Login to attend! |
|||
</a> |
|||
} |
|||
</div> |
|||
<div class="mt-4 event-form p-4"> |
|||
<span class="font-weight-bold"><i class="fas fa-user-friends"></i> Attendees <span class="float-right font-weight-normal" style="opacity:.65;">(@Event.Attendees.Count)</span></span> |
|||
<ul class="mt-1 mb-0 att-list"> |
|||
@foreach (var attendee in Event.Attendees) |
|||
{ |
|||
<li><i class="fa fa-check"></i> @attendee.UserName</li> |
|||
} |
|||
</ul> |
|||
</div> |
|||
</Column> |
|||
</Row> |
|||
} |
|||
```` |
|||
|
|||
* Create `EventDetail.razor.cs` file with the following content: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EventOrganizer.Events; |
|||
using Microsoft.AspNetCore.Components; |
|||
|
|||
namespace EventOrganizer.Blazor.Pages |
|||
{ |
|||
public partial class EventDetail |
|||
{ |
|||
[Parameter] |
|||
public string Id { get; set; } |
|||
|
|||
private EventDetailDto Event { get; set; } |
|||
private bool IsRegistered { get; set; } |
|||
|
|||
private readonly IEventAppService _eventAppService; |
|||
private readonly NavigationManager _navigationManager; |
|||
|
|||
public EventDetail( |
|||
IEventAppService eventAppService, |
|||
NavigationManager navigationManager) |
|||
{ |
|||
_eventAppService = eventAppService; |
|||
_navigationManager = navigationManager; |
|||
} |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
await GetEventAsync(); |
|||
} |
|||
|
|||
private async Task GetEventAsync() |
|||
{ |
|||
Event = await _eventAppService.GetAsync(Guid.Parse(Id)); |
|||
if (CurrentUser.IsAuthenticated) |
|||
{ |
|||
IsRegistered = Event.Attendees.Any(a => a.UserId == CurrentUser.Id); |
|||
} |
|||
} |
|||
|
|||
private async Task Register() |
|||
{ |
|||
await _eventAppService.RegisterAsync(Guid.Parse(Id)); |
|||
await GetEventAsync(); |
|||
} |
|||
|
|||
private async Task UnRegister() |
|||
{ |
|||
await _eventAppService.UnregisterAsync(Guid.Parse(Id)); |
|||
await GetEventAsync(); |
|||
} |
|||
|
|||
private async Task Delete() |
|||
{ |
|||
if (!await Message.Confirm("This event will be deleted: " + Event.Title)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await _eventAppService.DeleteAsync(Guid.Parse(Id)); |
|||
_navigationManager.NavigateTo("/"); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
The resulting page is shown below: |
|||
|
|||
 |
|||
|
|||
### Integration Tests |
|||
|
|||
Create an `EventAppService_Tests` class in the `EventOrganizer.Application.Tests` project: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace EventOrganizer.Events |
|||
{ |
|||
[Collection(EventOrganizerTestConsts.CollectionDefinitionName)] |
|||
public class EventAppService_Tests : EventOrganizerApplicationTestBase |
|||
{ |
|||
private readonly IEventAppService _eventAppService; |
|||
|
|||
public EventAppService_Tests() |
|||
{ |
|||
_eventAppService = GetRequiredService<IEventAppService>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Create_A_Valid_Event() |
|||
{ |
|||
// Create an event |
|||
|
|||
var eventId = await _eventAppService.CreateAsync( |
|||
new EventCreationDto |
|||
{ |
|||
Title = "My test event 1", |
|||
Description = "My test event description 1", |
|||
IsFree = true, |
|||
StartTime = DateTime.Now.AddDays(2) |
|||
} |
|||
); |
|||
|
|||
eventId.ShouldNotBe(Guid.Empty); |
|||
|
|||
// Get the event |
|||
|
|||
var @event = await _eventAppService.GetAsync(eventId); |
|||
@event.Title.ShouldBe("My test event 1"); |
|||
|
|||
// Get upcoming events |
|||
|
|||
var events = await _eventAppService.GetUpcomingAsync(); |
|||
events.ShouldContain(x => x.Title == "My test event 1"); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
## Source Code |
|||
|
|||
Source code of the completed application is [available on GitHub](https://github.com/abpframework/abp-samples/tree/master/EventOrganizer). |
|||
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 865 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 18 KiB |
@ -1,15 +1,13 @@ |
|||
# Data Access |
|||
|
|||
## Database Providers |
|||
|
|||
ABP framework was designed as database agnostic. It can work any type of data source by the help of the [repository](Repositories.md) and [unit of work](Unit-Of-Work.md) abstractions. However, currently the following providers are implemented: |
|||
ABP framework was designed as database agnostic. It can work any type of data source by the help of the [repository](Repositories.md) and [unit of work](Unit-Of-Work.md) abstractions. Currently, the following providers are implemented as official: |
|||
|
|||
* [Entity Framework Core](Entity-Framework-Core.md) (works with [various DBMS and providers](https://docs.microsoft.com/en-us/ef/core/providers/).) |
|||
* [MongoDB](MongoDB.md) |
|||
* [Dapper](Dapper.md) |
|||
|
|||
More providers will be added in the future. |
|||
|
|||
## See Also |
|||
|
|||
* [Connection Strings](Connection-Strings.md) |
|||
* [Connection Strings](Connection-Strings.md) |
|||
* [Data Seeding](Data-Seeding.md) |
|||
* [Data Filtering](Data-Filtering.md) |
|||
@ -0,0 +1,65 @@ |
|||
# Distributed Event Bus Rebus Integration |
|||
|
|||
> This document explains **how to configure the [Rebus](http://mookid.dk/category/rebus/)** as the distributed event bus provider. See the [distributed event bus document](Distributed-Event-Bus.md) to learn how to use the distributed event bus system |
|||
|
|||
## Installation |
|||
|
|||
Use the ABP CLI to add [Volo.Abp.EventBus.Rebus](https://www.nuget.org/packages/Volo.Abp.EventBus.Rebus) NuGet package to your project: |
|||
|
|||
* Install the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) if you haven't installed before. |
|||
* Open a command line (terminal) in the directory of the `.csproj` file you want to add the `Volo.Abp.EventBus.Rebus` package. |
|||
* Run `abp add-package Volo.Abp.EventBus.Rebus` command. |
|||
|
|||
If you want to do it manually, install the [Volo.Abp.EventBus.Rebus](https://www.nuget.org/packages/Volo.Abp.EventBus.Rebus) NuGet package to your project and add `[DependsOn(typeof(AbpEventBusRebusModule))]` to the [ABP module](Module-Development-Basics.md) class inside your project. |
|||
|
|||
## Configuration |
|||
|
|||
You can configure using the standard [configuration system](Configuration.md), like using the [options](Options.md) classes. |
|||
|
|||
### The Options Classes |
|||
|
|||
`AbpRebusEventBusOptions` classe can be used to configure the event bus options for the Rebus. |
|||
|
|||
You can configure this options inside the `PreConfigureServices` of your [module](Module-Development-Basics.md). |
|||
|
|||
**Example: Minimize configuration** |
|||
|
|||
```csharp |
|||
PreConfigure<AbpRebusEventBusOptions>(options => |
|||
{ |
|||
options.InputQueueName = "eventbus"; |
|||
}); |
|||
``` |
|||
|
|||
Rebus has many options, you can use the `Configurer` property of `AbpRebusEventBusOptions` class to configure. |
|||
|
|||
Default events are **stored in memory**. See the [rebus document](https://github.com/rebus-org/Rebus/wiki/Transport) for more details. |
|||
|
|||
**Example: Configure the store** |
|||
|
|||
````csharp |
|||
PreConfigure<AbpRebusEventBusOptions>(options => |
|||
{ |
|||
options.InputQueueName = "eventbus"; |
|||
options.Configurer = rebusConfigurer => |
|||
{ |
|||
rebusConfigurer.Transport(t => t.UseMsmq("eventbus")); |
|||
rebusConfigurer.Subscriptions(s => s.UseJsonFile(@"subscriptions.json")); |
|||
}; |
|||
}); |
|||
```` |
|||
|
|||
You can use the `Publish` properpty of `AbpRebusEventBusOptions` class to change the publishing method |
|||
|
|||
**Example: Configure the event publishing** |
|||
|
|||
````csharp |
|||
PreConfigure<AbpRebusEventBusOptions>(options => |
|||
{ |
|||
options.InputQueueName = "eventbus"; |
|||
options.Publish = async (bus, type, data) => |
|||
{ |
|||
await bus.Publish(data); |
|||
}; |
|||
}); |
|||
```` |
|||