diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 46cd1cb470..c6010b777b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -148,6 +148,10 @@ "SuccessfullySent": "Successfully Sent", "SuccessfullyDeleted": "Successfully Deleted", "DiscountRequestDeletionWarningMessage": "Discount request will be deleted" , - "BusinessType": "Business Type" + "BusinessType": "Business Type", + "TotalQuestionCount": "Total question count", + "RemainingQuestionCount": "Remaining question count", + "TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount must be greater than RemainingQuestionCount !", + "QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount and RemainingQuestionCount must be zero or greater than zero !" } } \ No newline at end of file diff --git a/docs/en/CLI.md b/docs/en/CLI.md index 75e3e027b4..d9b6832dd5 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -40,7 +40,7 @@ abp new Acme.BookStore #### Options * `--template` or `-t`: Specifies the template name. Default template name is `app`, which generates a web application. Available templates: - * `app` (default): [Application template](Startup-Templates/Application.md). Additional options: + * **`app`** (default): [Application template](Startup-Templates/Application.md). Additional options: * `--ui` or `-u`: Specifies the UI framework. Default framework is `mvc`. Available frameworks: * `mvc`: ASP.NET Core MVC. There are some additional options for this template: * `--tiered`: Creates a tiered solution where Web and Http API layers are physically separated. If not specified, it creates a layered solution which is less complex and suitable for most scenarios. @@ -51,10 +51,10 @@ abp new Acme.BookStore * `--mobile` or `-m`: Specifies the mobile application framework. Default framework is `react-native`. Available frameworks: * `none`: no mobile application. * `react-native`: React Native. - * `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers: - * `ef`: Entity Framework Core. - * `mongodb`: MongoDB. - * `module`: [Module template](Startup-Templates/Module.md). Additional options: + * `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers: + * `ef`: Entity Framework Core. + * `mongodb`: MongoDB. + * **`module`**: [Module template](Startup-Templates/Module.md). Additional options: * `--no-ui`: Specifies to not include the UI. This makes possible to create service-only modules (a.k.a. microservices - without UI). * `--output-folder` or `-o`: Specifies the output folder. Default value is the current directory. * `--version` or `-v`: Specifies the ABP & template version. It can be a [release tag](https://github.com/abpframework/abp/releases) or a [branch name](https://github.com/abpframework/abp/branches). Uses the latest release if not specified. Most of the times, you will want to use the latest version. diff --git a/docs/en/Dapper.md b/docs/en/Dapper.md index d8b17838eb..26fbf97e66 100644 --- a/docs/en/Dapper.md +++ b/docs/en/Dapper.md @@ -1,22 +1,24 @@ # Dapper Integration -Because Dapper's idea is that the sql statement takes precedence, and mainly provides some extension methods for the `IDbConnection` interface. +Dapper is a light-weight and simple database provider. The major benefit of using Dapper is writing T-SQL queries. It provides some extension methods for `IDbConnection` interface. -Abp does not encapsulate too many functions for Dapper. Abp Dapper provides a `DapperRepository` base class based on Abp EntityFrameworkCore, which provides the `IDbConnection` and `IDbTransaction` properties required by Dapper. - -These two properties can work well with [Unit-Of-Work](Unit-Of-Work.md). +ABP does not encapsulate many functions for Dapper. ABP Dapper library provides a `DapperRepository` base class based on ABP EntityFrameworkCore module, which provides the `IDbConnection` and `IDbTransaction` properties required by Dapper. `IDbConnection` and `IDbTransaction` works well with the [ABP Unit-Of-Work](Unit-Of-Work.md). ## Installation -Please install and configure EF Core according to [EF Core's integrated documentation](Entity-Framework-Core.md). +Install and configure EF Core according to [EF Core's integrated documentation](Entity-Framework-Core.md). + +`Volo.Abp.Dapper` is the library for the Dapper integration. + +You can find it on NuGet Gallery: https://www.nuget.org/packages/Volo.Abp.Dapper -`Volo.Abp.Dapper` is the main nuget package for the Dapper integration. Install it to your project (for a layered application, to your data/infrastructure layer): +Install it to your project (for a layered application, to your data/infrastructure layer): ```shell Install-Package Volo.Abp.Dapper ``` -Then add `AbpDapperModule` module dependency (`DependsOn` attribute) to your [module](Module-Development-Basics.md): +Then add `AbpDapperModule` module dependency (with `DependsOn` attribute) to your [module](Module-Development-Basics.md): ````C# using Volo.Abp.Dapper; @@ -34,9 +36,10 @@ namespace MyCompany.MyProject ## Implement Dapper Repository -The following code implements the `Person` repository, which requires EF Core's `DbContext` (MyAppDbContext). You can inject `PersonDapperRepository` to call its methods. +The following code creates the `PersonRepository`, which requires EF Core's `DbContext` (MyAppDbContext). +You can inject `PersonDapperRepository` to your services for your database operations. -`DbConnection` and `DbTransaction` are from the `DapperRepository` base class. +`DbConnection` and `DbTransaction` comes from the `DapperRepository` base class. ```C# public class PersonDapperRepository : DapperRepository, ITransientDependency diff --git a/docs/en/Object-Extensions.md b/docs/en/Object-Extensions.md index 40a7ddd5ea..8c7cca4037 100644 --- a/docs/en/Object-Extensions.md +++ b/docs/en/Object-Extensions.md @@ -200,17 +200,17 @@ ObjectExtensionManager.Instance ````csharp ObjectExtensionManager.Instance - .AddOrUpdateProperty( - "MyIntProperty", + .AddOrUpdateProperty( + "MyDateTimeProperty", options => { - options.DefaultValueFactory = () => 42; + options.DefaultValueFactory = () => DateTime.Now; }); ```` `options.DefaultValueFactory` has a higher priority than the `options.DefaultValue` . -> Tip: Use `DefaultValueFactory` option only if the default value may change over the time. If it is a constant value, then use the `DefaultValue` option. +> Tip: Use `DefaultValueFactory` option only if the default value may change over the time (like `DateTime.Now` in this example). If it is a constant value, then use the `DefaultValue` option. #### CheckPairDefinitionOnMapping diff --git a/docs/en/SignalR-Integration.md b/docs/en/SignalR-Integration.md index 0a2ebdaa54..f318967888 100644 --- a/docs/en/SignalR-Integration.md +++ b/docs/en/SignalR-Integration.md @@ -1,6 +1,6 @@ # SignalR Integration -> It is already possible to follow [the standard Microsoft tutorial](https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr) to add [SignalR](https://docs.microsoft.com/en-us/aspnet/core/signalr/introduction) to your application. However, ABP provides a SignalR integration packages that simplify the integration and usage. +> It is already possible to follow [the standard Microsoft tutorial](https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr) to add [SignalR](https://docs.microsoft.com/en-us/aspnet/core/signalr/introduction) to your application. However, ABP provides a SignalR integration packages those simplify the integration and usage. ## Installation @@ -224,4 +224,14 @@ ABP implements SignalR's `IUserIdProvider` interface to provide the current user See the [SignalR Integration Demo](https://github.com/abpframework/abp-samples/tree/master/SignalRDemo) as a sample application. It has a simple Chat page to send messages between (authenticated) users. -![signalr-demo-chat](images/signalr-demo-chat.png) \ No newline at end of file +![signalr-demo-chat](images/signalr-demo-chat.png) + +## Remarks + +ABP Framework doesn't change the SignalR. It works in your ABP Framework based application just like any other ASP.NET Core application. + +Refer to the Microsoft's documentation to [host and scale](https://docs.microsoft.com/en-us/aspnet/core/signalr/scale) your application, integrate to [Azure](https://docs.microsoft.com/en-us/aspnet/core/signalr/publish-to-azure-web-app) or [Redis backplane](https://docs.microsoft.com/en-us/aspnet/core/signalr/redis-backplane)... etc. + +## See Also + +* [Microsoft SignalR documentation](https://docs.microsoft.com/en-us/aspnet/core/signalr/introduction) \ No newline at end of file diff --git a/docs/en/Text-Templating.md b/docs/en/Text-Templating.md index 18a360c5c8..c71787f598 100644 --- a/docs/en/Text-Templating.md +++ b/docs/en/Text-Templating.md @@ -204,13 +204,14 @@ Inline localization uses the [localization system](Localization.md) to localize Assuming you need to send an email to a user to reset her/his password. Here, the template content: ```` -{%{{{L "ResetMyPassword"}}}%} +{%{{{L "ResetMyPassword" model.name}}}%} ```` `L` function is used to localize the given key based on the current user culture. You need to define the `ResetMyPassword` key inside your localization file: ````json -"ResetMyPassword": "Click here to reset your password" +"ResetMyPasswordTitle": "Reset my password", +"ResetMyPassword": "Hi {0}, Click here to reset your password" ```` You also need to declare the localization resource to be used with this template, inside your template definition provider class: @@ -234,6 +235,7 @@ var result = await _templateRenderer.RenderAsync( "PasswordReset", //the template name new PasswordResetModel { + Name = "john", Link = "https://abp.io/example-link?userId=123&token=ABC" } ); @@ -242,7 +244,7 @@ var result = await _templateRenderer.RenderAsync( You will see the localized result: ````csharp -Click here to reset your password +Hi john, Click here to reset your password ```` > If you define the [default localization resource](Localization.md) for your application, then no need to declare the resource type for the template definition. diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md b/docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md index df23fd649c..8f664a80a5 100644 --- a/docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md @@ -88,6 +88,8 @@ You can set some of the attributes on your c# property, or directly on html tag. * `label`: Sets the label for input. * `display-required-symbol`: Adds the required symbol (*) to label if input is required. Default `True`. +`asp-format`, `name` and `value` attributes of [Asp.Net Core Input Tag Helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-input-tag-helper) are also valid for `abp-input` tag helper. + ### Label & Localization You can set label of your input in different ways: @@ -258,4 +260,4 @@ You can set some of the attributes on your c# property, or directly on html tag. #### Tag Attributes - `asp-items`: Sets the select data. This Should be a list of SelectListItem. -- `Inline`: If true, radio buttons will be in single line, next to each other. If false, they will be under each other. \ No newline at end of file +- `Inline`: If true, radio buttons will be in single line, next to each other. If false, they will be under each other. diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs index 83093e0370..d15870e7c1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs @@ -9,6 +9,5 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending public Dictionary Properties { get; set; } public Dictionary Configuration { get; set; } - } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumDto.cs new file mode 100644 index 0000000000..4f2dc526eb --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +{ + [Serializable] + public class ExtensionEnumDto + { + public List Fields { get; set; } + + public string LocalizationResource { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumFieldDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumFieldDto.cs new file mode 100644 index 0000000000..ddc7c349d4 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumFieldDto.cs @@ -0,0 +1,12 @@ +using System; + +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +{ + [Serializable] + public class ExtensionEnumFieldDto + { + public string Name { get; set; } + + public object Value { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs index fd9665eab1..0338bbd4dc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs @@ -7,5 +7,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending public class ObjectExtensionsDto { public Dictionary Modules { get; set; } + + public Dictionary Enums { get; set; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs index d925fd11e8..761b72ec99 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs @@ -2,20 +2,31 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.TagHelpers; using System.Text.Encodings.Web; -using Volo.Abp.Threading; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions { public static class TagHelperExtensions { - public static async Task ProcessAndGetOutputAsync(this TagHelper tagHelper, TagHelperAttributeList attributeList, TagHelperContext context, string tagName = "div", TagMode tagMode = TagMode.SelfClosing) + public static async Task ProcessAndGetOutputAsync( + this TagHelper tagHelper, + TagHelperAttributeList attributeList, + TagHelperContext context, + string tagName = "div", + TagMode tagMode = TagMode.SelfClosing) { - var innerOutput = new TagHelperOutput(tagName, attributeList, (useCachedResult, encoder) => Task.Run(() => new DefaultTagHelperContent())) + var innerOutput = new TagHelperOutput( + tagName, + attributeList, + (useCachedResult, encoder) => Task.Run(() => new DefaultTagHelperContent())) { TagMode = tagMode }; - - var innerContext = new TagHelperContext(attributeList, context.Items, Guid.NewGuid().ToString()); + + var innerContext = new TagHelperContext( + attributeList, + context.Items, + Guid.NewGuid().ToString() + ); tagHelper.Init(context); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs index f264d21cd5..16a700f4bc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs @@ -33,6 +33,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form [ViewContext] public ViewContext ViewContext { get; set; } + [HtmlAttributeName("asp-format")] + public string Format { get; set; } + + public string Name { get; set; } + + public string Value { get; set; } + public AbpInputTagHelper(AbpInputTagHelperService tagHelperService) : base(tagHelperService) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs index a2bb92a14d..4ddf44d2d6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs @@ -91,7 +91,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form inputHtml + label : label + inputHtml; - return innerContent + infoHtml + validation; + return innerContent + infoHtml + validation; } protected virtual string SurroundInnerHtmlAndGet(TagHelperContext context, TagHelperOutput output, string innerHtml, bool isCheckbox) @@ -103,30 +103,56 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form protected virtual TagHelper GetInputTagHelper(TagHelperContext context, TagHelperOutput output) { - var textAreaAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute