mirror of https://github.com/abpframework/abp.git
345 changed files with 7799 additions and 582 deletions
@ -0,0 +1,121 @@ |
|||||
|
# ABP Framework 3.2 RC with the new Blazor UI |
||||
|
|
||||
|
We are extremely excited today to release the ABP Framework (and the ABP Commercial, as always) version `3.2.0-rc.1` (Release Candidate). This release includes an early preview version of the **Blazor UI** for the ABP.IO Platform. |
||||
|
|
||||
|
## The Blazor UI |
||||
|
|
||||
|
While the Blazor UI should be considered as **experimental** for now, it is possible to develop your application today. |
||||
|
|
||||
|
### Fundamental Services |
||||
|
|
||||
|
Currently implemented some important framework features; |
||||
|
|
||||
|
* **Authentication** through the MVC backend using the OpenId Connect authorization code flow. So, all the current login options (login, register, forgot password, external/social logins...) are supported. |
||||
|
* **Authorization**, using the ABP Framework **permissions** as well as the standard authorization system. |
||||
|
* **Localization** just works like the MVC UI. |
||||
|
* **Basic Theme** with top main menu. |
||||
|
* **Dynamic C# HTTP API proxies**, so you can directly consume your backend API by injecting the application service interfaces. |
||||
|
* Some other **fundamental services** like ISettingProvider, IFeatureChecker, ICurrentUser |
||||
|
|
||||
|
Also, the standard .net services are already available, like caching, logging, validation and much more. Since the ABP Framework is layered itself, all the non MVC UI related features are already available. |
||||
|
|
||||
|
### Pre-Built Modules |
||||
|
|
||||
|
And some modules have been implemented; |
||||
|
|
||||
|
* **Identity** module is pre-installed and provides user**, role and permission management**. |
||||
|
* **Profile management** page is implemented to allow to change password and personal settings. |
||||
|
|
||||
|
### About the Blazorise Library |
||||
|
|
||||
|
We've selected the [Blazorise](https://blazorise.com/) as a fundamental UI library for the Blazor UI. It already support different HTML/CSS frameworks and significantly increases the developer productivity. |
||||
|
|
||||
|
We also have a good news: **[Mladen Macanović](https://github.com/stsrki)**, the creator of the Blazorise, is **joining to the core ABP Framework team** in the next weeks. We are excited to work with him to bring the power of these two successfully projects together. |
||||
|
|
||||
|
### The Tutorial |
||||
|
|
||||
|
We are currently in progress of updating the web application development tutorial for the Blazor UI. Follow the [@abpframework](https://twitter.com/abpframework) Twitter account to get informed once it's done. |
||||
|
|
||||
|
### Get started with the Blazor UI |
||||
|
|
||||
|
If you want to try the Blazor UI today, follow the instructions below. |
||||
|
|
||||
|
First, install the the latest [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) preview version: |
||||
|
|
||||
|
````bash |
||||
|
dotnet tool update Volo.Abp.Cli -g --version 3.2.0-rc.1 |
||||
|
```` |
||||
|
|
||||
|
Then you can create a new solution using the *abp new* command: |
||||
|
|
||||
|
````bash |
||||
|
abp new AbpBlazorDemo -u blazor |
||||
|
```` |
||||
|
|
||||
|
> See the ABP CLI documentation for the additional options, like MongoDB database or separated authentication server. |
||||
|
|
||||
|
Open the generated solution using the latest Visual Studio 2019. You will see a solution structure like the picture below: |
||||
|
|
||||
|
TODO |
||||
|
|
||||
|
* Run the `.DbMigrator` project to create the database and seed the initial data. |
||||
|
* Run the `HttpApi.Host` project for the server side. |
||||
|
* Run the `.Blazor` project to start the Blazor UI. |
||||
|
|
||||
|
Use `admin` as the username as `1q2w3E*` as the password to login to the application. |
||||
|
|
||||
|
TODO |
||||
|
|
||||
|
## What's New with the ABP Framework 3.2 |
||||
|
|
||||
|
Beside the Blazor UI, there are a lot of issues have been closed with [the milestone 3.2](https://github.com/abpframework/abp/milestone/39?closed=1). I will highlight some of the major features and changes released with this version. |
||||
|
|
||||
|
### MongoDB ACID Transactions |
||||
|
|
||||
|
[MongoDB integration](https://docs.abp.io/en/abp/latest/MongoDB) now supports multi-document transactions that comes with the MongoDB 4.x. |
||||
|
|
||||
|
> Transactions are disabled for automated integration tests coming with the application startup template, since the Mongo2Go library (we use in the test projects) has a problem with the transactions. We've sent a [Pull Request](https://github.com/Mongo2Go/Mongo2Go/pull/101) to fix it and will enable the transactions again when they merge & release it. |
||||
|
> |
||||
|
> If you are upgrading an existing solution and using MongoDB, please disable transactions for the test projects by following the [Unit Of Work](https://docs.abp.io/en/abp/latest/Unit-Of-Work) documentation. |
||||
|
|
||||
|
### Kafka Integration for the Distributed Event Bus |
||||
|
|
||||
|
ABP Framework's [distributed event system](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus) has been [integrated to RabbitMQ](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus-RabbitMQ-Integration) before. By the version 3.2, it has a Kafka integration package, named [Volo.Abp.EventBus.Kafka](https://www.nuget.org/packages/Volo.Abp.EventBus.Kafka). |
||||
|
|
||||
|
See the [Kafka integration documentation](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus-Kafka-Integration) to learn how to install and configure it. |
||||
|
|
||||
|
### Host Features |
||||
|
|
||||
|
TODO |
||||
|
|
||||
|
### AbpHttpClientBuilderOptions |
||||
|
|
||||
|
TODO |
||||
|
|
||||
|
### Account Module: Profile Management Page Extensions |
||||
|
|
||||
|
TODO |
||||
|
|
||||
|
### ABP Build Command |
||||
|
|
||||
|
We are using **mono repository** approach and the [abp repository](https://github.com/abpframework/abp) has tens of solutions and hundreds of projects (the framework, modules, tooling, templates...) with all of them are referencing to each other. |
||||
|
|
||||
|
It gets a significant time to build the whole repository for every Git push. To **optimize** this process, we've created the **abp build** command in the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI): |
||||
|
|
||||
|
````bash |
||||
|
abp build |
||||
|
```` |
||||
|
|
||||
|
We will use this command to build the abp repository or a solution inside it. However it is available to everyone in case of need. |
||||
|
|
||||
|
> **Most of the people will not need it**. If you need it, see the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) document to learn all the details and options. |
||||
|
|
||||
|
### Other Features, Improvements and Changes |
||||
|
|
||||
|
* Introduced the `DynamicRangeAttribute` that can be used to determine the range values on runtime, just like the `DynamicStringLengthAttribute` was introduced before. |
||||
|
* Improved the feature management modal for multi-tenant applications to group features on the UI and show hierarchically. |
||||
|
* Added `--skip-cli-version-check` option to ABP CLI to improve the performance by bypassing the online version check. |
||||
|
* Angular UI now redirect to MVC UI (the authentication server side) for profile management page, if the authorization code flow is used (which is the default). |
||||
|
* Improvements and optimizations for the [Angular service proxy generation](https://blog.abp.io/abp/Introducing-the-Angular-Service-Proxy-Generation). |
||||
|
|
||||
|
And a lot of minor improvements and bug fixes. You can see [the milestone 3.2](https://github.com/abpframework/abp/milestone/39?closed=1) for all issues & PRs closed with this version. |
||||
@ -0,0 +1,67 @@ |
|||||
|
# Build Command |
||||
|
|
||||
|
Building a .NET project is hard when the project references a project reference outside of the solution or even from a different GIT repository. This command builds a GIT repository and it's depending repositories or a single .NET solution File. In order ```build``` command to work, its **executing directory** or passed ```--working-directory``` parameter's directory must contain one of; |
||||
|
|
||||
|
* A .NET solution file (*.sln) |
||||
|
* abp-build-config.json |
||||
|
|
||||
|
When the executing directory (or ```--working-directory``` parameter's directory) contains a .NET solution file, ```build``` command builds all the projects in the related solution file and all project references on building project files recursively. |
||||
|
|
||||
|
When the executing directory (or ```--working-directory``` parameter's directory) contains a ```abp-build-config.json```, ```build``` command builds all changed projects form its last build and all project references on building project files recursively. |
||||
|
|
||||
|
# Build Command Config |
||||
|
|
||||
|
```abp-build-config.json``` contains properties below; |
||||
|
|
||||
|
* ```Name```: Name of the GIT repository. This can be friendly name of your GIT repository or any other unique string for the repository. |
||||
|
* ```RootPath```: Root path of the repository which contains ```.git``` folder. |
||||
|
* ```DependingRepositories```: Depending repository list of a repository. Each depending repository item contains same fields as a repository. |
||||
|
* ```IgnoredDirectories```: Relative directory paths to ignore while building a GIT repository. |
||||
|
|
||||
|
A sample ```abp-build-config.json``` looks like for a Windows OS; |
||||
|
|
||||
|
````json |
||||
|
{ |
||||
|
"Name": "main-repository", |
||||
|
"RootPath": "D:\\GitHub\\main-repository", |
||||
|
"DependingRepositories": [{ |
||||
|
"Name": "module-repository", |
||||
|
"RootPath": "D:\\GitHub\\module-repository" |
||||
|
}], |
||||
|
"IgnoredDirectories": [ |
||||
|
"utils" |
||||
|
] |
||||
|
} |
||||
|
```` |
||||
|
|
||||
|
# Build Status |
||||
|
|
||||
|
ABP CLI stores a build status file for builds using the repository friendly names and current branch names in the; |
||||
|
|
||||
|
* ```%USERPROFILE%\.abp\build\``` for Windows. |
||||
|
* ```$HOME/.abp/build/``` for Linux/macOS. |
||||
|
|
||||
|
and uses this file when building same repository next time and only builds affected projects and decreases the total build time. A sample build status file content looks like; |
||||
|
|
||||
|
````json |
||||
|
{ |
||||
|
"RepositoryName": "main-repository", |
||||
|
"BranchName": "dev", |
||||
|
"CommitId": "84ecde8ba275aeeb14d24a87ad46a1e941adf8ba", |
||||
|
"SucceedProjects": [{ |
||||
|
"CsProjPath": "D:\\GitHub\\main-repository\\BookStore\\BookStore.Web.csproj", |
||||
|
"CommitId": "84ecde8ba275aeeb14d24a87ad46a1e941adf8ba" |
||||
|
}], |
||||
|
"DependingRepositories": [{ |
||||
|
"RepositoryName": "module-repository", |
||||
|
"BranchName": "dev", |
||||
|
"CommitId": "0598b8e45af9507fc9ba8abf304e78fc7d434e04", |
||||
|
"SucceedProjects": [{ |
||||
|
"CsProjPath": "D:\\GitHub\\module-repository\\identity-module\Identity\\Identity.Web.csproj", |
||||
|
"CommitId": "0598b8e45af9507fc9ba8abf304e78fc7d434e04" |
||||
|
}], |
||||
|
"DependingRepositories": [] |
||||
|
}] |
||||
|
} |
||||
|
```` |
||||
|
|
||||
@ -1,5 +1,28 @@ |
|||||
# 身份管理模块 |
# 身份管理模块 |
||||
|
|
||||
身份模块基于Microsoft Identity 库用于管理[组织单元](Organization-Units.md), 角色, 用户和他们的权限. |
身份模块基于Microsoft Identity库用于管理[组织单元](Organization-Units.md), 角色, 用户和他们的权限. |
||||
|
|
||||
参阅 [源码](https://github.com/abpframework/abp/tree/dev/modules/identity). 文档很快会被完善. |
参阅 [源码](https://github.com/abpframework/abp/tree/dev/modules/identity). 文档很快会被完善. |
||||
|
|
||||
|
## Identity安全日志 |
||||
|
|
||||
|
安全日志可以记录账户的一些重要的操作或者改动, 你可以在在一些功能中保存安全日志. |
||||
|
|
||||
|
你可以注入和使用 `IdentitySecurityLogManager` 或 `ISecurityLogManager` 来保存安全日志. 默认它会创建一个安全日志对象并填充常用的值. 如 `CreationTime`, `ClientIpAddress`, `BrowserInfo`, `current user/tenant`等等. 当然你可以自定义这些值. |
||||
|
|
||||
|
```cs |
||||
|
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() |
||||
|
{ |
||||
|
Identity = "IdentityServer"; |
||||
|
Action = "ChangePassword"; |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
通过配置 `AbpSecurityLogOptions` 来提供应用程序的名称或者禁用安全日志功能. 默认是**启用**状态. |
||||
|
|
||||
|
```cs |
||||
|
Configure<AbpSecurityLogOptions>(options => |
||||
|
{ |
||||
|
options.ApplicationName = "AbpSecurityTest"; |
||||
|
}); |
||||
|
``` |
||||
|
|||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,50 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Authentication; |
||||
|
using Microsoft.AspNetCore.Authentication.OAuth.Claims; |
||||
|
using Microsoft.AspNetCore.Authentication.OpenIdConnect; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.AspNetCore.MultiTenancy; |
||||
|
|
||||
|
namespace Microsoft.Extensions.DependencyInjection |
||||
|
{ |
||||
|
public static class AbpOpenIdConnectExtensions |
||||
|
{ |
||||
|
public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder) |
||||
|
=> builder.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, _ => { }); |
||||
|
|
||||
|
public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, Action<OpenIdConnectOptions> configureOptions) |
||||
|
=> builder.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, configureOptions); |
||||
|
|
||||
|
public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, Action<OpenIdConnectOptions> configureOptions) |
||||
|
=> builder.AddAbpOpenIdConnect(authenticationScheme, OpenIdConnectDefaults.DisplayName, configureOptions); |
||||
|
|
||||
|
public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<OpenIdConnectOptions> configureOptions) |
||||
|
{ |
||||
|
return builder.AddOpenIdConnect(authenticationScheme, displayName, options => |
||||
|
{ |
||||
|
options.ClaimActions.MapAbpClaimTypes(); |
||||
|
|
||||
|
options.Events = new OpenIdConnectEvents |
||||
|
{ |
||||
|
OnAuthorizationCodeReceived = receivedContext => |
||||
|
{ |
||||
|
var tenantKey = receivedContext.HttpContext.RequestServices |
||||
|
.GetRequiredService<IOptionsSnapshot<AbpAspNetCoreMultiTenancyOptions>>().Value.TenantKey; |
||||
|
|
||||
|
if (receivedContext.HttpContext.Request != null && |
||||
|
receivedContext.Request.Cookies.ContainsKey(tenantKey)) |
||||
|
{ |
||||
|
receivedContext.TokenEndpointRequest.SetParameter(tenantKey, |
||||
|
receivedContext.Request.Cookies[tenantKey]); |
||||
|
} |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
configureOptions?.Invoke(options); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp3.1</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.1.6" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.AspNetCore.MultiTenancy\Volo.Abp.AspNetCore.MultiTenancy.csproj" /> |
||||
|
<ProjectReference Include="..\Volo.Abp.AspNetCore.Authentication.OAuth\Volo.Abp.AspNetCore.Authentication.OAuth.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Volo.Abp.AspNetCore.Authentication.OAuth; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Authentication.OpenIdConnect |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpMultiTenancyModule), |
||||
|
typeof(AbpAspNetCoreAuthenticationOAuthModule))] |
||||
|
public class AbpAspNetCoreAuthenticationOpenIdConnectModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming; |
||||
|
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule) |
||||
|
)] |
||||
|
public class AbpAspNetCoreComponentsWebAssemblyBasicThemeModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpRouterOptions>(options => |
||||
|
{ |
||||
|
options.AdditionalAssemblies.Add(typeof(AbpAspNetCoreComponentsWebAssemblyBasicThemeModule).Assembly); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,7 @@ |
|||||
|
@page "/authentication/{action}" |
||||
|
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
||||
|
<RemoteAuthenticatorView Action="@Action" /> |
||||
|
|
||||
|
@code{ |
||||
|
[Parameter] public string Action { get; set; } |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
@using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing |
||||
|
@using Microsoft.Extensions.Options |
||||
|
@inject IOptions<AbpRouterOptions> RouterOptions |
||||
|
<CascadingAuthenticationState> |
||||
|
<Router AppAssembly="RouterOptions.Value.AppAssembly" |
||||
|
AdditionalAssemblies="RouterOptions.Value.AdditionalAssemblies"> |
||||
|
<Found Context="routeData"> |
||||
|
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> |
||||
|
<NotAuthorized> |
||||
|
@if (!context.User.Identity.IsAuthenticated) |
||||
|
{ |
||||
|
<RedirectToLogin /> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<p>You are not authorized to access this resource.</p> |
||||
|
} |
||||
|
</NotAuthorized> |
||||
|
</AuthorizeRouteView> |
||||
|
</Found> |
||||
|
<NotFound> |
||||
|
<LayoutView Layout="@typeof(MainLayout)"> |
||||
|
<p>Sorry, there's nothing at this address.</p> |
||||
|
</LayoutView> |
||||
|
</NotFound> |
||||
|
</Router> |
||||
|
</CascadingAuthenticationState> |
||||
@ -0,0 +1,65 @@ |
|||||
|
@using Volo.Abp.Localization |
||||
|
@using System.Globalization |
||||
|
@using System.Collections.Immutable |
||||
|
@inject ILanguageProvider LanguageProvider |
||||
|
@inject IJSRuntime JsRuntime |
||||
|
@if (_otherLanguages != null && _otherLanguages.Any()) |
||||
|
{ |
||||
|
<Dropdown> |
||||
|
<DropdownToggle Color="Color.None"> |
||||
|
@_currentLanguage.DisplayName |
||||
|
</DropdownToggle> |
||||
|
<DropdownMenu> |
||||
|
@foreach (var language in _otherLanguages) |
||||
|
{ |
||||
|
<DropdownItem Clicked="() => ChangeLanguageAsync(language)">@language.DisplayName</DropdownItem> |
||||
|
} |
||||
|
</DropdownMenu> |
||||
|
</Dropdown> |
||||
|
} |
||||
|
@code { |
||||
|
private IReadOnlyList<LanguageInfo> _otherLanguages; |
||||
|
private LanguageInfo _currentLanguage; |
||||
|
|
||||
|
protected override async Task OnInitializedAsync() |
||||
|
{ |
||||
|
var selectedLanguageName = await JsRuntime.InvokeAsync<string>( |
||||
|
"localStorage.getItem", |
||||
|
"Abp.SelectedLanguage" |
||||
|
); |
||||
|
|
||||
|
_otherLanguages = await LanguageProvider.GetLanguagesAsync(); |
||||
|
|
||||
|
if (!_otherLanguages.Any()) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!selectedLanguageName.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
_currentLanguage = _otherLanguages.FirstOrDefault(l => l.UiCultureName == selectedLanguageName); |
||||
|
} |
||||
|
|
||||
|
if (_currentLanguage == null) |
||||
|
{ |
||||
|
_currentLanguage = _otherLanguages.FirstOrDefault(l => l.UiCultureName == CultureInfo.CurrentUICulture.Name); |
||||
|
} |
||||
|
|
||||
|
if (_currentLanguage == null) |
||||
|
{ |
||||
|
_currentLanguage = _otherLanguages.FirstOrDefault(); |
||||
|
} |
||||
|
|
||||
|
_otherLanguages = _otherLanguages.Where(l => l != _currentLanguage).ToImmutableList(); |
||||
|
} |
||||
|
|
||||
|
private async Task ChangeLanguageAsync(LanguageInfo language) |
||||
|
{ |
||||
|
await JsRuntime.InvokeVoidAsync( |
||||
|
"localStorage.setItem", |
||||
|
"Abp.SelectedLanguage", language.UiCultureName |
||||
|
); |
||||
|
|
||||
|
await JsRuntime.InvokeVoidAsync("location.reload"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
||||
|
@using Volo.Abp.Users |
||||
|
@inject ICurrentUser CurrentUser |
||||
|
@inject NavigationManager Navigation |
||||
|
@inject SignOutSessionStateManager SignOutManager |
||||
|
<AuthorizeView> |
||||
|
<Authorized> |
||||
|
<Dropdown> |
||||
|
<DropdownToggle Color="Color.None"> |
||||
|
@CurrentUser.UserName |
||||
|
</DropdownToggle> |
||||
|
<DropdownMenu> |
||||
|
@if (Menu != null) |
||||
|
{ |
||||
|
@foreach (var menuItem in Menu.Items) |
||||
|
{ |
||||
|
<DropdownItem Clicked="@(() => NavigateTo(menuItem.Url))">@menuItem.DisplayName</DropdownItem> |
||||
|
} |
||||
|
} |
||||
|
<Divider /> |
||||
|
<DropdownItem Clicked="BeginSignOut">Logout</DropdownItem> |
||||
|
</DropdownMenu> |
||||
|
</Dropdown> |
||||
|
</Authorized> |
||||
|
<NotAuthorized> |
||||
|
<a class="nav-link" href="authentication/login">Log in</a> |
||||
|
</NotAuthorized> |
||||
|
</AuthorizeView> |
||||
|
@code{ |
||||
|
|
||||
|
private void NavigateTo(string uri) |
||||
|
{ |
||||
|
Navigation.NavigateTo(uri); |
||||
|
} |
||||
|
|
||||
|
private async Task BeginSignOut() |
||||
|
{ |
||||
|
await SignOutManager.SetSignOutState(); |
||||
|
NavigateTo("authentication/logout"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Volo.Abp.UI.Navigation; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic |
||||
|
{ |
||||
|
public partial class LoginDisplay |
||||
|
{ |
||||
|
[Inject] protected IMenuManager MenuManager { get; set; } |
||||
|
|
||||
|
protected ApplicationMenu Menu { get; set; } |
||||
|
|
||||
|
protected override async Task OnInitializedAsync() |
||||
|
{ |
||||
|
Menu = await MenuManager.GetAsync(StandardMenus.User); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
@inherits LayoutComponentBase |
||||
|
@using Volo.Abp.Ui.Branding |
||||
|
@inject IBrandingProvider BrandingProvider |
||||
|
<nav class="navbar navbar-expand-md navbar-dark bg-dark shadow-sm flex-column flex-md-row mb-4" id="main-navbar" style="min-height: 4rem;"> |
||||
|
<div class="container"> |
||||
|
<a class="navbar-brand" href="/">@BrandingProvider.AppName</a> |
||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" |
||||
|
data-target="#main-navbar-collapse" aria-controls="main-navbar-collapse" |
||||
|
aria-expanded="false" aria-label="Toggle navigation"> |
||||
|
<span class="navbar-toggler-icon"></span> |
||||
|
</button> |
||||
|
<div class="collapse navbar-collapse" id="main-navbar-collapse"> |
||||
|
<ul class="navbar-nav mx-auto"> |
||||
|
<NavMenu/> |
||||
|
</ul> |
||||
|
<ul class="navbar-nav"> |
||||
|
<li class="nav-item"> |
||||
|
<LanguageSwitch/> |
||||
|
</li> |
||||
|
<li class="nav-item"> |
||||
|
<LoginDisplay/> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<div class="container"> |
||||
|
@Body |
||||
|
</div> |
||||
@ -0,0 +1,7 @@ |
|||||
|
@if (Menu != null) |
||||
|
{ |
||||
|
foreach (var menuItem in Menu.Items) |
||||
|
{ |
||||
|
<NavMenuItem MenuItem="@menuItem" /> |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Volo.Abp.UI.Navigation; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic |
||||
|
{ |
||||
|
public partial class NavMenu |
||||
|
{ |
||||
|
[Inject] protected IMenuManager MenuManager { get; set; } |
||||
|
|
||||
|
protected ApplicationMenu Menu { get; set; } |
||||
|
|
||||
|
private bool collapseNavMenu = true; |
||||
|
|
||||
|
private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; |
||||
|
|
||||
|
protected override async Task OnInitializedAsync() |
||||
|
{ |
||||
|
Menu = await MenuManager.GetAsync(StandardMenus.Main); |
||||
|
} |
||||
|
|
||||
|
private void ToggleNavMenu() |
||||
|
{ |
||||
|
collapseNavMenu = !collapseNavMenu; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
@using Volo.Abp.UI.Navigation |
||||
|
@{ |
||||
|
var elementId = MenuItem.ElementId ?? "MenuItem_" + MenuItem.Name.Replace(".", "_"); |
||||
|
var cssClass = string.IsNullOrEmpty(MenuItem.CssClass) ? string.Empty : MenuItem.CssClass; |
||||
|
var url = string.IsNullOrEmpty(MenuItem.Url) ? "#" : MenuItem.Url; |
||||
|
} |
||||
|
@if (MenuItem.IsLeaf) |
||||
|
{ |
||||
|
if (MenuItem.Url != null) |
||||
|
{ |
||||
|
<li class="nav-item @cssClass" disabled="@MenuItem.IsDisabled"> |
||||
|
<NavLink class="nav-link" href="@url" id="@elementId"> |
||||
|
@if (MenuItem.Icon != null) |
||||
|
{ |
||||
|
if (MenuItem.Icon.StartsWith("fa")) |
||||
|
{ |
||||
|
<i class="@MenuItem.Icon"></i> |
||||
|
} |
||||
|
} |
||||
|
@MenuItem.DisplayName |
||||
|
</NavLink> |
||||
|
</li> |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<li class="nav-item"> |
||||
|
<div class="dropdown"> |
||||
|
<a class="nav-link dropdown-toggle" href="#" id="@elementId" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
||||
|
@if (MenuItem.Icon != null) |
||||
|
{ |
||||
|
if (MenuItem.Icon.StartsWith("fa")) |
||||
|
{ |
||||
|
<i class="@MenuItem.Icon"></i> |
||||
|
} |
||||
|
} |
||||
|
@MenuItem.DisplayName |
||||
|
</a> |
||||
|
<div class="dropdown-menu border-0 shadow-sm" aria-labelledby="@elementId"> |
||||
|
@foreach (var childMenuItem in MenuItem.Items) |
||||
|
{ |
||||
|
<NavMenuItem MenuItem="@childMenuItem" /> |
||||
|
} |
||||
|
</div> |
||||
|
</div> |
||||
|
</li> |
||||
|
|
||||
|
} |
||||
|
@code { |
||||
|
[Parameter] |
||||
|
public ApplicationMenuItem MenuItem { get; set; } |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
@inject NavigationManager Navigation |
||||
|
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
||||
|
@code { |
||||
|
protected override void OnInitialized() |
||||
|
{ |
||||
|
Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
@using System.Net.Http |
||||
|
@using Microsoft.AspNetCore.Components.Authorization |
||||
|
@using Microsoft.AspNetCore.Components.Forms |
||||
|
@using Microsoft.AspNetCore.Components.Routing |
||||
|
@using Microsoft.AspNetCore.Components.Web |
||||
|
@using Microsoft.AspNetCore.Components.WebAssembly.Http |
||||
|
@using Microsoft.JSInterop |
||||
|
@using Volo.Abp.AspNetCore.Components.WebAssembly |
||||
|
@using Blazorise |
||||
|
@using Blazorise.DataGrid |
||||
@ -0,0 +1,16 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Razor"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.1</TargetFramework> |
||||
|
<RazorLangVersion>3.0</RazorLangVersion> |
||||
|
<PackageId>Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme</PackageId> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.WebAssembly.Theming\Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,105 @@ |
|||||
|
|
||||
|
#main-navbar-tools a.dropdown-toggle { |
||||
|
text-decoration: none; |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.navbar .dropdown-submenu { |
||||
|
position: relative; |
||||
|
} |
||||
|
.navbar .dropdown-menu { |
||||
|
margin: 0; |
||||
|
padding: 0; |
||||
|
} |
||||
|
.navbar .dropdown-menu a { |
||||
|
font-size: .9em; |
||||
|
padding: 10px 15px; |
||||
|
display: block; |
||||
|
min-width: 210px; |
||||
|
text-align: left; |
||||
|
border-radius: 0.25rem; |
||||
|
min-height: 44px; |
||||
|
} |
||||
|
.navbar .dropdown-submenu a::after { |
||||
|
transform: rotate(-90deg); |
||||
|
position: absolute; |
||||
|
right: 16px; |
||||
|
top: 18px; |
||||
|
} |
||||
|
.navbar .dropdown-submenu .dropdown-menu { |
||||
|
top: 0; |
||||
|
left: 100%; |
||||
|
} |
||||
|
|
||||
|
.card-header .btn { |
||||
|
padding: 2px 6px; |
||||
|
} |
||||
|
.card-header h5 { |
||||
|
margin: 0; |
||||
|
} |
||||
|
.container > .card { |
||||
|
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; |
||||
|
} |
||||
|
|
||||
|
@media screen and (min-width: 768px) { |
||||
|
.navbar .dropdown:hover > .dropdown-menu { |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
.navbar .dropdown-submenu:hover > .dropdown-menu { |
||||
|
display: block; |
||||
|
} |
||||
|
} |
||||
|
.input-validation-error { |
||||
|
border-color: #dc3545; |
||||
|
} |
||||
|
.field-validation-error { |
||||
|
font-size: 0.8em; |
||||
|
} |
||||
|
|
||||
|
.dataTables_scrollBody { |
||||
|
min-height: 248px; |
||||
|
} |
||||
|
|
||||
|
div.dataTables_wrapper div.dataTables_info { |
||||
|
padding-top: 11px; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
div.dataTables_wrapper div.dataTables_length label { |
||||
|
padding-top: 10px; |
||||
|
margin-bottom: 0; |
||||
|
} |
||||
|
|
||||
|
.rtl .dropdown-menu-right { |
||||
|
right: auto; |
||||
|
left: 0; |
||||
|
} |
||||
|
|
||||
|
.rtl .dropdown-menu-right a { |
||||
|
text-align: right; |
||||
|
} |
||||
|
|
||||
|
.rtl .navbar .dropdown-menu a { |
||||
|
text-align: right; |
||||
|
} |
||||
|
.rtl .navbar .dropdown-submenu .dropdown-menu { |
||||
|
top: 0; |
||||
|
left: auto; |
||||
|
right: 100%; |
||||
|
} |
||||
|
|
||||
|
/* TEMP */ |
||||
|
|
||||
|
.navbar-dark .navbar-nav .nav-link { |
||||
|
color: #000 !important; |
||||
|
} |
||||
|
|
||||
|
.navbar-nav > .nav-item > .nav-link, |
||||
|
.navbar-nav > .nav-item > .dropdown > .nav-link { |
||||
|
color: #fff !important; |
||||
|
} |
||||
|
|
||||
|
.navbar-nav>.nav-item>div>button{ |
||||
|
color:#fff; |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
$(function () { |
||||
|
$('.dropdown-menu a.dropdown-toggle').on('click', function (e) { |
||||
|
if (!$(this).next().hasClass('show')) { |
||||
|
$(this).parents('.dropdown-menu').first().find('.show').removeClass("show"); |
||||
|
} |
||||
|
|
||||
|
var $subMenu = $(this).next(".dropdown-menu"); |
||||
|
$subMenu.toggleClass('show'); |
||||
|
|
||||
|
$(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function (e) { |
||||
|
$('.dropdown-submenu .show').removeClass("show"); |
||||
|
}); |
||||
|
|
||||
|
return false; |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,17 @@ |
|||||
|
using Volo.Abp.BlazoriseUI; |
||||
|
using Volo.Abp.Http.Client.IdentityModel.WebAssembly; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.UI.Navigation; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpBlazoriseUIModule), |
||||
|
typeof(AbpHttpClientIdentityModelWebAssemblyModule), |
||||
|
typeof(AbpUiNavigationModule) |
||||
|
)] |
||||
|
public class AbpAspNetCoreComponentsWebAssemblyThemingModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System.Reflection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing |
||||
|
{ |
||||
|
public class AbpRouterOptions |
||||
|
{ |
||||
|
public Assembly AppAssembly { get; set; } |
||||
|
|
||||
|
public RouterAssemblyList AdditionalAssemblies { get; } |
||||
|
|
||||
|
public AbpRouterOptions() |
||||
|
{ |
||||
|
AdditionalAssemblies = new RouterAssemblyList(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Reflection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing |
||||
|
{ |
||||
|
public class RouterAssemblyList : List<Assembly> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Razor"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.1</TargetFramework> |
||||
|
<RazorLangVersion>3.0</RazorLangVersion> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.BlazoriseUI\Volo.Abp.BlazoriseUI.csproj" /> |
||||
|
<ProjectReference Include="..\Volo.Abp.Http.Client.IdentityModel.WebAssembly\Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj" /> |
||||
|
<ProjectReference Include="..\Volo.Abp.UI.Navigation\Volo.Abp.UI.Navigation.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,51 @@ |
|||||
|
using System; |
||||
|
using System.Reflection; |
||||
|
using System.Threading.Tasks; |
||||
|
using JetBrains.Annotations; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Components.WebAssembly; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Client; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting |
||||
|
{ |
||||
|
public static class AbpWebAssemblyHostBuilderExtensions |
||||
|
{ |
||||
|
public static IAbpApplicationWithExternalServiceProvider AddApplication<TStartupModule>( |
||||
|
[NotNull] this WebAssemblyHostBuilder builder, |
||||
|
Action<AbpWebAssemblyApplicationCreationOptions> options) |
||||
|
where TStartupModule : IAbpModule |
||||
|
{ |
||||
|
Check.NotNull(builder, nameof(builder)); |
||||
|
|
||||
|
builder.Services.AddSingleton<IConfiguration>(builder.Configuration); |
||||
|
builder.Services.AddSingleton(builder); |
||||
|
|
||||
|
var application = builder.Services.AddApplication<TStartupModule>(opts => |
||||
|
{ |
||||
|
options?.Invoke(new AbpWebAssemblyApplicationCreationOptions(builder, opts)); |
||||
|
}); |
||||
|
|
||||
|
return application; |
||||
|
} |
||||
|
|
||||
|
public static async Task InitializeAsync( |
||||
|
[NotNull] this IAbpApplicationWithExternalServiceProvider application, |
||||
|
[NotNull] IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
Check.NotNull(application, nameof(application)); |
||||
|
Check.NotNull(serviceProvider, nameof(serviceProvider)); |
||||
|
|
||||
|
application.Initialize(serviceProvider); |
||||
|
|
||||
|
using (var scope = serviceProvider.CreateScope()) |
||||
|
{ |
||||
|
await scope.ServiceProvider |
||||
|
.GetRequiredService<ICachedApplicationConfigurationClient>() |
||||
|
.InitializeAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.1</TargetFramework> |
||||
|
<AssemblyName>Volo.Abp.AspNetCore.Components.WebAssembly</AssemblyName> |
||||
|
<PackageId>Volo.Abp.AspNetCore.Components.WebAssembly</PackageId> |
||||
|
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Client.Common\Volo.Abp.AspNetCore.Mvc.Client.Common.csproj" /> |
||||
|
<ProjectReference Include="..\Volo.Abp.UI\Volo.Abp.UI.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.1" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="3.1.6" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,26 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Client; |
||||
|
using Volo.Abp.Http.Client; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.UI; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpAspNetCoreMvcClientCommonModule), |
||||
|
typeof(AbpUiModule) |
||||
|
)] |
||||
|
public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<AbpHttpClientBuilderOptions>(options => |
||||
|
{ |
||||
|
options.ProxyClientBuildActions.Add((_, builder) => |
||||
|
{ |
||||
|
builder.AddHttpMessageHandler<AbpBlazorClientHttpMessageHandler>(); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
using System; |
||||
|
using System.Net.Http; |
||||
|
using System.Net.Http.Headers; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.JSInterop; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
||||
|
{ |
||||
|
public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDependency |
||||
|
{ |
||||
|
private readonly IJSRuntime _jsRuntime; |
||||
|
|
||||
|
public AbpBlazorClientHttpMessageHandler(IJSRuntime jsRuntime) |
||||
|
{ |
||||
|
_jsRuntime = jsRuntime; |
||||
|
} |
||||
|
|
||||
|
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) |
||||
|
{ |
||||
|
await SetLanguageAsync(request, cancellationToken); |
||||
|
|
||||
|
return await base.SendAsync(request, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
private async Task SetLanguageAsync(HttpRequestMessage request, CancellationToken cancellationToken) |
||||
|
{ |
||||
|
var selectedLanguage = await _jsRuntime.InvokeAsync<string>( |
||||
|
"localStorage.getItem", |
||||
|
cancellationToken, |
||||
|
"Abp.SelectedLanguage" |
||||
|
); |
||||
|
|
||||
|
if (!selectedLanguage.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
request.Headers.AcceptLanguage.Clear(); |
||||
|
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(selectedLanguage)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
||||
|
{ |
||||
|
public class AbpWebAssemblyApplicationCreationOptions |
||||
|
{ |
||||
|
public WebAssemblyHostBuilder HostBuilder { get; } |
||||
|
|
||||
|
public AbpApplicationCreationOptions ApplicationCreationOptions { get; } |
||||
|
|
||||
|
public AbpWebAssemblyApplicationCreationOptions( |
||||
|
WebAssemblyHostBuilder hostBuilder, |
||||
|
AbpApplicationCreationOptions applicationCreationOptions) |
||||
|
{ |
||||
|
HostBuilder = hostBuilder; |
||||
|
ApplicationCreationOptions = applicationCreationOptions; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
||||
|
{ |
||||
|
public class ApplicationConfigurationCache : ISingletonDependency |
||||
|
{ |
||||
|
protected ApplicationConfigurationDto Configuration { get; set; } |
||||
|
|
||||
|
public virtual ApplicationConfigurationDto Get() |
||||
|
{ |
||||
|
return Configuration; |
||||
|
} |
||||
|
|
||||
|
internal void Set(ApplicationConfigurationDto configuration) |
||||
|
{ |
||||
|
Configuration = configuration; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
||||
|
{ |
||||
|
public interface IUiMessageService |
||||
|
{ |
||||
|
Task InfoAsync(string message, string title = null); |
||||
|
|
||||
|
Task SuccessAsync(string message, string title = null); |
||||
|
|
||||
|
Task WarnAsync(string message, string title = null); |
||||
|
|
||||
|
Task ErrorAsync(string message, string title = null); |
||||
|
|
||||
|
Task<bool> ConfirmAsync(string message, string title = null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.JSInterop; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
||||
|
{ |
||||
|
//TODO: Implement with sweetalert in a new package
|
||||
|
public class UiMessageService : IUiMessageService, ITransientDependency |
||||
|
{ |
||||
|
protected IJSRuntime JsRuntime { get; } |
||||
|
|
||||
|
public UiMessageService(IJSRuntime jsRuntime) |
||||
|
{ |
||||
|
JsRuntime = jsRuntime; |
||||
|
} |
||||
|
|
||||
|
public async Task InfoAsync(string message, string title = null) |
||||
|
{ |
||||
|
await JsRuntime.InvokeVoidAsync("alert", message); |
||||
|
} |
||||
|
|
||||
|
public async Task SuccessAsync(string message, string title = null) |
||||
|
{ |
||||
|
await JsRuntime.InvokeVoidAsync("alert", message); |
||||
|
} |
||||
|
|
||||
|
public async Task WarnAsync(string message, string title = null) |
||||
|
{ |
||||
|
await JsRuntime.InvokeVoidAsync("alert", message); |
||||
|
} |
||||
|
|
||||
|
public async Task ErrorAsync(string message, string title = null) |
||||
|
{ |
||||
|
await JsRuntime.InvokeVoidAsync("alert", message); |
||||
|
} |
||||
|
|
||||
|
public async Task<bool> ConfirmAsync(string message, string title = null) |
||||
|
{ |
||||
|
return await JsRuntime.InvokeAsync<bool>("confirm", message); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Client; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Http.Client.DynamicProxying; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
||||
|
{ |
||||
|
public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency |
||||
|
{ |
||||
|
protected IHttpClientProxy<IAbpApplicationConfigurationAppService> Proxy { get; } |
||||
|
|
||||
|
protected ApplicationConfigurationCache Cache { get; } |
||||
|
|
||||
|
public WebAssemblyCachedApplicationConfigurationClient( |
||||
|
IHttpClientProxy<IAbpApplicationConfigurationAppService> proxy, |
||||
|
ApplicationConfigurationCache cache) |
||||
|
{ |
||||
|
Proxy = proxy; |
||||
|
Cache = cache; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task InitializeAsync() |
||||
|
{ |
||||
|
Cache.Set(await Proxy.Service.GetAsync()); |
||||
|
} |
||||
|
|
||||
|
public virtual Task<ApplicationConfigurationDto> GetAsync() |
||||
|
{ |
||||
|
return Task.FromResult(GetConfigurationByChecking()); |
||||
|
} |
||||
|
|
||||
|
public virtual ApplicationConfigurationDto Get() |
||||
|
{ |
||||
|
return GetConfigurationByChecking(); |
||||
|
} |
||||
|
|
||||
|
private ApplicationConfigurationDto GetConfigurationByChecking() |
||||
|
{ |
||||
|
var configuration = Cache.Get(); |
||||
|
if (configuration == null) |
||||
|
{ |
||||
|
throw new AbpException( |
||||
|
$"{nameof(WebAssemblyCachedApplicationConfigurationClient)} should be initialized before using it."); |
||||
|
} |
||||
|
|
||||
|
return configuration; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Security.Claims; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Client; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Security.Claims; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
||||
|
{ |
||||
|
public class WebAssemblyCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ITransientDependency |
||||
|
{ |
||||
|
protected ICachedApplicationConfigurationClient ConfigurationClient { get; } |
||||
|
|
||||
|
public WebAssemblyCurrentPrincipalAccessor( |
||||
|
ICachedApplicationConfigurationClient configurationClient) |
||||
|
{ |
||||
|
ConfigurationClient = configurationClient; |
||||
|
} |
||||
|
|
||||
|
protected override ClaimsPrincipal GetClaimsPrincipal() |
||||
|
{ |
||||
|
var configuration = ConfigurationClient.Get(); |
||||
|
|
||||
|
var claims = new List<Claim>(); |
||||
|
|
||||
|
if (!configuration.CurrentUser.UserName.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
claims.Add(new Claim(AbpClaimTypes.UserName,configuration.CurrentUser.UserName)); |
||||
|
} |
||||
|
|
||||
|
if (!configuration.CurrentUser.Email.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
claims.Add(new Claim(AbpClaimTypes.Email,configuration.CurrentUser.Email)); |
||||
|
} |
||||
|
|
||||
|
if (configuration.CurrentUser.Id != null) |
||||
|
{ |
||||
|
claims.Add(new Claim(AbpClaimTypes.UserId,configuration.CurrentUser.Id.ToString())); |
||||
|
} |
||||
|
|
||||
|
if (configuration.CurrentUser.TenantId != null) |
||||
|
{ |
||||
|
claims.Add(new Claim(AbpClaimTypes.TenantId,configuration.CurrentUser.TenantId.ToString())); |
||||
|
} |
||||
|
else if (configuration.CurrentTenant.Id != null) |
||||
|
{ |
||||
|
claims.Add(new Claim(AbpClaimTypes.TenantId,configuration.CurrentTenant.Id.ToString())); |
||||
|
} |
||||
|
|
||||
|
foreach (var role in configuration.CurrentUser.Roles) |
||||
|
{ |
||||
|
claims.Add(new Claim(AbpClaimTypes.Role, role)); |
||||
|
} |
||||
|
|
||||
|
return new ClaimsPrincipal(new ClaimsIdentity(claims)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Mvc.MultiTenancy; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Http.Client.DynamicProxying; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.Threading; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
||||
|
{ |
||||
|
public class WebAssemblyRemoteTenantStore : ITenantStore, ITransientDependency |
||||
|
{ |
||||
|
protected IHttpClientProxy<IAbpTenantAppService> Proxy { get; } |
||||
|
|
||||
|
public WebAssemblyRemoteTenantStore( |
||||
|
IHttpClientProxy<IAbpTenantAppService> proxy) |
||||
|
{ |
||||
|
Proxy = proxy; |
||||
|
} |
||||
|
|
||||
|
public async Task<TenantConfiguration> FindAsync(string name) |
||||
|
{ |
||||
|
//TODO: Cache
|
||||
|
|
||||
|
return CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name)); |
||||
|
} |
||||
|
|
||||
|
public async Task<TenantConfiguration> FindAsync(Guid id) |
||||
|
{ |
||||
|
//TODO: Cache
|
||||
|
|
||||
|
return CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id)); |
||||
|
} |
||||
|
|
||||
|
public TenantConfiguration Find(string name) |
||||
|
{ |
||||
|
//TODO: Cache
|
||||
|
|
||||
|
return AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name))); |
||||
|
} |
||||
|
|
||||
|
public TenantConfiguration Find(Guid id) |
||||
|
{ |
||||
|
//TODO: Cache
|
||||
|
|
||||
|
return AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id))); |
||||
|
} |
||||
|
|
||||
|
protected virtual TenantConfiguration CreateTenantConfiguration(FindTenantResultDto tenantResultDto) |
||||
|
{ |
||||
|
if (!tenantResultDto.Success || tenantResultDto.TenantId == null) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name); |
||||
|
} |
||||
|
|
||||
|
protected virtual string CreateCacheKey(string tenantName) |
||||
|
{ |
||||
|
return $"RemoteTenantStore_Name_{tenantName}"; |
||||
|
} |
||||
|
|
||||
|
protected virtual string CreateCacheKey(Guid tenantId) |
||||
|
{ |
||||
|
return $"RemoteTenantStore_Id_{tenantId:N}"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using System.Linq; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.MultiTenancy |
||||
|
{ |
||||
|
public class FormTenantResolveContributor : HttpTenantResolveContributorBase |
||||
|
{ |
||||
|
public const string ContributorName = "Form"; |
||||
|
|
||||
|
public override string Name => ContributorName; |
||||
|
|
||||
|
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) |
||||
|
{ |
||||
|
if (httpContext.Request == null || !httpContext.Request.Form.Any()) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
return httpContext.Request.Form[context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,24 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<AssemblyName>Volo.Abp.AspNetCore.Mvc.Client.Common</AssemblyName> |
||||
|
<PackageId>Volo.Abp.AspNetCore.Mvc.Client.Common</PackageId> |
||||
|
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Contracts\Volo.Abp.AspNetCore.Mvc.Contracts.csproj" /> |
||||
|
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.csproj" /> |
||||
|
<ProjectReference Include="..\Volo.Abp.Http.Client\Volo.Abp.Http.Client.csproj" /> |
||||
|
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,33 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Caching; |
||||
|
using Volo.Abp.Http.Client; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.Client |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpHttpClientModule), |
||||
|
typeof(AbpAspNetCoreMvcContractsModule), |
||||
|
typeof(AbpCachingModule), |
||||
|
typeof(AbpLocalizationModule) |
||||
|
)] |
||||
|
public class AbpAspNetCoreMvcClientCommonModule : AbpModule |
||||
|
{ |
||||
|
public const string RemoteServiceName = "AbpMvcClient"; |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddHttpClientProxies( |
||||
|
typeof(AbpAspNetCoreMvcContractsModule).Assembly, |
||||
|
RemoteServiceName, |
||||
|
asDefaultServices: false |
||||
|
); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.GlobalContributors.Add<RemoteLocalizationContributor>(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,33 +1,11 @@ |
|||||
using Microsoft.Extensions.DependencyInjection; |
using Volo.Abp.Modularity; |
||||
using Volo.Abp.Caching; |
|
||||
using Volo.Abp.Http.Client; |
|
||||
using Volo.Abp.Localization; |
|
||||
using Volo.Abp.Modularity; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.Mvc.Client |
namespace Volo.Abp.AspNetCore.Mvc.Client |
||||
{ |
{ |
||||
[DependsOn( |
[DependsOn( |
||||
typeof(AbpHttpClientModule), |
typeof(AbpAspNetCoreMvcClientCommonModule) |
||||
typeof(AbpAspNetCoreMvcContractsModule), |
|
||||
typeof(AbpCachingModule), |
|
||||
typeof(AbpLocalizationModule) |
|
||||
)] |
)] |
||||
public class AbpAspNetCoreMvcClientModule : AbpModule |
public class AbpAspNetCoreMvcClientModule : AbpModule |
||||
{ |
{ |
||||
public const string RemoteServiceName = "AbpMvcClient"; |
|
||||
|
|
||||
public override void ConfigureServices(ServiceConfigurationContext context) |
|
||||
{ |
|
||||
context.Services.AddHttpClientProxies( |
|
||||
typeof(AbpAspNetCoreMvcContractsModule).Assembly, |
|
||||
RemoteServiceName, |
|
||||
asDefaultServices: false |
|
||||
); |
|
||||
|
|
||||
Configure<AbpLocalizationOptions>(options => |
|
||||
{ |
|
||||
options.GlobalContributors.Add<RemoteLocalizationContributor>(); |
|
||||
}); |
|
||||
} |
|
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,23 @@ |
|||||
|
using System; |
||||
|
using Autofac; |
||||
|
using JetBrains.Annotations; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Components.WebAssembly; |
||||
|
|
||||
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting |
||||
|
{ |
||||
|
public static class AbpWebAssemblyApplicationCreationOptionsAutofacExtensions |
||||
|
{ |
||||
|
public static void UseAutofac( |
||||
|
[NotNull] this AbpWebAssemblyApplicationCreationOptions options, |
||||
|
[CanBeNull] Action<ContainerBuilder> configure = null) |
||||
|
{ |
||||
|
options.HostBuilder.Services.AddAutofacServiceProviderFactory(); |
||||
|
options.HostBuilder.ConfigureContainer( |
||||
|
options.HostBuilder.Services.GetSingletonInstance<IServiceProviderFactory<ContainerBuilder>>(), |
||||
|
configure |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.1</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.WebAssembly\Volo.Abp.AspNetCore.Components.WebAssembly.csproj" /> |
||||
|
<ProjectReference Include="..\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Volo.Abp.AspNetCore.Components.WebAssembly; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.Autofac.WebAssembly |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpAutofacModule), |
||||
|
typeof(AbpAspNetCoreComponentsWebAssemblyModule) |
||||
|
)] |
||||
|
public class AbpAutofacWebAssemblyModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue