diff --git a/.editorconfig b/.editorconfig
index 03ef2d8bf..03ae84d98 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,37 +1,85 @@
-; EditorConfig to support per-solution formatting.
-; Use the EditorConfig VS add-in to make this work.
-; http://editorconfig.org/
-;
-; Here are some resources for what's supported for .NET/C#
-; https://kent-boogaart.com/blog/editorconfig-reference-for-c-developers
-; https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference?view=vs-2017
-;
-; Be **careful** editing this because some of the rules don't support adding a severity level
-; For instance if you change to `dotnet_sort_system_directives_first = true:warning` (adding `:warning`)
-; then the rule will be silently ignored.
-
-; This is the default for the codeline.
+# EditorConfig: https://editorconfig.org
root = true
[*]
indent_style = space
+indent_size = 4
+end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
-[*.cs]
-indent_size = 4
-dotnet_sort_system_directives_first = true
+[*.md]
+trim_trailing_whitespace = false
-[*.{xml,config,*proj,nuspec,props,resx,targets,yml,tasks,cshtml,html}]
+[*.{json,yml,yaml}]
indent_size = 2
-[*.json]
+[*.{csproj,props,targets,nuspec,xml,config,resx,tasks,cshtml,html}]
indent_size = 2
-[*.{ps1,psm1}]
+[*.{ps1,psm1,sh}]
indent_size = 4
-[*.sh]
-indent_size = 4
-end_of_line = lf
\ No newline at end of file
+[*.cs]
+# Namespace
+dotnet_style_namespace_match_folder = true
+
+# Using directives
+dotnet_sort_system_directives_first = true
+dotnet_separate_import_directive_groups = false
+
+# this. qualification
+dotnet_style_qualification_for_field = false:suggestion
+dotnet_style_qualification_for_property = false:suggestion
+dotnet_style_qualification_for_method = false:suggestion
+dotnet_style_qualification_for_event = false:suggestion
+
+# Language keywords vs BCL types
+dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
+dotnet_style_predefined_type_for_member_access = true:suggestion
+
+# var preferences
+csharp_style_var_for_built_in_types = false:suggestion
+csharp_style_var_when_type_is_apparent = true:suggestion
+csharp_style_var_elsewhere = false:suggestion
+
+# Expression-level preferences
+csharp_style_expression_bodied_methods = when_on_single_line:suggestion
+csharp_style_expression_bodied_constructors = false:suggestion
+csharp_style_expression_bodied_properties = true:suggestion
+csharp_style_expression_bodied_accessors = true:suggestion
+
+# Pattern matching
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+
+# Null checking
+csharp_style_throw_expression = true:suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+
+# Formatting
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_space_after_cast = false
+csharp_space_after_keywords_in_control_flow_statements = true
+
+# Naming conventions
+dotnet_naming_rule.private_fields_should_be_camel_case.severity = suggestion
+dotnet_naming_rule.private_fields_should_be_camel_case.symbols = private_fields
+dotnet_naming_rule.private_fields_should_be_camel_case.style = camel_case_prefix
+
+dotnet_naming_symbols.private_fields.applicable_kinds = field
+dotnet_naming_symbols.private_fields.applicable_accessibilities = private
+
+dotnet_naming_style.camel_case_prefix.capitalization = camel_case
+dotnet_naming_style.camel_case_prefix.required_prefix = _
+
+# Severity overrides - don't break build for style
+dotnet_analyzer_diagnostic.category-Style.severity = suggestion
diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml
index 348aab62c..eaa0d1f76 100644
--- a/.github/workflows/ci-build.yml
+++ b/.github/workflows/ci-build.yml
@@ -14,7 +14,14 @@ jobs:
dotnet-version: '8.0.x'
- run: dotnet restore WalkingTec.Mvvm.sln
- run: dotnet build WalkingTec.Mvvm.sln --no-restore -c Release
- - run: dotnet test WalkingTec.Mvvm.sln --no-build -c Release --verbosity normal
+ - name: Test
+ run: dotnet test WalkingTec.Mvvm.sln --no-build -c Release --verbosity normal --logger "trx;LogFileName=test-results.trx"
+ - name: Upload test results
+ uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: test-results
+ path: "**/test-results.trx"
security-scan:
runs-on: ubuntu-latest
needs: build-and-test
diff --git a/WTM-8.1.13-SPEC.md b/WTM-8.1.13-SPEC.md
new file mode 100644
index 000000000..23b81c22f
--- /dev/null
+++ b/WTM-8.1.13-SPEC.md
@@ -0,0 +1,542 @@
+# WTM 8.1.13 Security Patches - Claude CLI Execution Spec
+
+## Overview
+
+This document is the **single source of truth** for implementing P0/P1 security and quality fixes on the WTM fork (`cct08311github/WTM`, `dotnet8` branch). Designed for Claude CLI automated execution.
+
+**Repository:** https://github.com/cct08311github/WTM
+**Branch:** `dotnet8` (base), create `feature/8.1.13-security` for work
+**Current version:** WTM 8.1.12, targeting net8.0
+
+---
+
+## Execution Order (7 tasks, each = 1 git commit)
+
+| Task | ID | Priority | Type | Risk |
+|------|----|----------|------|------|
+| 1 | P1-1 | HIGH | Dependency removal | Low |
+| 2 | P1-2 | HIGH | Dependency replacement | Medium |
+| 3 | P0-1a | CRITICAL | New file | Low |
+| 4 | P0-1b | CRITICAL | Code modification (multiple files) | Medium |
+| 5 | P0-2 | CRITICAL | New files + code modification | Medium |
+| 6 | P1-3 | HIGH | Code modification | Medium |
+| 7 | CI | INFRA | New file | Low |
+
+Before starting: `git checkout dotnet8 && git checkout -b feature/8.1.13-security`
+
+---
+## GitHub Issues to Create (5 total, create ALL before starting code changes)
+
+### Issue #1
+```
+Title: [P1-1] Remove legacy .NET Core 2.1.x dependencies
+Labels: security, dependencies, P1
+```
+Body: Three NuGet packages reference .NET Core 2.1.x (EOL Aug 2021): Microsoft.AspNetCore.Http 2.1.34 (Core.csproj), Microsoft.AspNetCore.Mvc.ViewFeatures 2.1.3 (TagHelpers.LayUI.csproj), Microsoft.AspNetCore.Razor.Runtime 2.1.2 (TagHelpers.LayUI.csproj), System.IO.FileSystem 4.3.0 (unnecessary polyfill). All types included in .NET 8 shared framework. Replace with FrameworkReference. Risk: Low | Effort: 0.5 day
+
+### Issue #2
+```
+Title: [P1-2] Replace abandoned DotNetCore.NPOI with official NPOI 2.7.6
+Labels: security, dependencies, P1
+```
+Body: DotNetCore.NPOI 1.2.3 is abandoned fork with no security patches. Official NPOI actively maintained at 2.7.x. API compatible, same namespaces. Risk: Medium | Effort: 1-2 days
+
+### Issue #3
+```
+Title: [P0-1][CRITICAL] Replace MD5 password hashing with PBKDF2
+Labels: security, critical, P0
+```
+Body: Login uses bare Utils.GetMD5String(password) - unsalted MD5. Vulnerable to rainbow table attacks. Fails CISSP/SOC2 compliance. Fix: Add PasswordHashHelper with PBKDF2, transparent verify-and-upgrade migration. DB migration: ALTER TABLE FrameworkUser ALTER COLUMN Password NVARCHAR(256). Risk: Medium | Effort: 2-3 days
+
+### Issue #4
+```
+Title: [P0-2][CRITICAL] Implement JWT refresh token with rotation
+Labels: security, critical, P0
+```
+Body: TokenService.cs returns RefreshToken = "". No refresh mechanism. Fix: Add RefreshTokenEntity, implement rotation with reuse detection, expand ITokenService, add API endpoints. DB migration: CREATE TABLE FrameworkRefreshTokens. Risk: Low (additive) | Effort: 2-3 days
+
+### Issue #5
+```
+Title: [P1-3] Fix sync-over-async patterns (ThreadPool starvation)
+Labels: performance, P1
+```
+Body: ~20+ .Result/.Wait() on async methods. Highest risk: DoLogin() on every auth request. Key locations: WTMContext.cs DoLogin (6x), _WorkflowApiController.cs (5x), ApproveActivity.cs (5x). Fix: Add DoLoginAsync, keep sync wrapper [Obsolete]. Risk: Medium | Effort: 2-3 days
+
+---
+## Task 1: Remove Legacy .NET Core 2.1.x Dependencies [P1-1]
+
+### File: `src/WalkingTec.Mvvm.Core/WalkingTec.Mvvm.Core.csproj`
+
+DELETE this line:
+```xml
+
+```
+
+ADD this ItemGroup (after existing PackageReference ItemGroup):
+```xml
+
+
+
+```
+
+### File: `src/WalkingTec.Mvvm.TagHelpers.LayUI/WalkingTec.Mvvm.TagHelpers.LayUI.csproj`
+
+DELETE these 3 lines:
+```xml
+
+
+
+```
+
+REPLACE the now-empty ItemGroup with:
+```xml
+
+
+
+```
+
+### Verify: `dotnet build WalkingTec.Mvvm.sln -c Release`
+
+### Commit message:
+```
+fix(deps): remove legacy .NET Core 2.1.x dependencies [P1-1]
+
+- Remove Microsoft.AspNetCore.Http 2.1.34 from Core.csproj
+- Remove Mvc.ViewFeatures 2.1.3, Razor.Runtime 2.1.2, System.IO.FileSystem 4.3.0 from TagHelpers.LayUI.csproj
+- Add FrameworkReference to Microsoft.AspNetCore.App (both projects)
+Closes #1
+```
+
+---
+
+## Task 2: Replace DotNetCore.NPOI [P1-2]
+
+### File: `src/WalkingTec.Mvvm.Core/WalkingTec.Mvvm.Core.csproj`
+
+REPLACE:
+```xml
+
+```
+WITH:
+```xml
+
+```
+
+Also check: `grep -rn "using DotNetCore" src/ --include="*.cs"` - if any found, change to `using NPOI`.
+
+### Verify: `dotnet build WalkingTec.Mvvm.sln -c Release`
+
+### Commit message:
+```
+fix(deps): replace abandoned DotNetCore.NPOI with official NPOI 2.7.6 [P1-2]
+Closes #2
+```
+
+---
+## Task 3: Add PasswordHashHelper [P0-1a]
+
+### NEW FILE: `src/WalkingTec.Mvvm.Core/PasswordHashHelper.cs`
+
+```csharp
+using System;
+using System.Security.Cryptography;
+using System.Text;
+using System.Text.RegularExpressions;
+using Microsoft.AspNetCore.Identity;
+
+namespace WalkingTec.Mvvm.Core
+{
+ public static class PasswordHashHelper
+ {
+ private static readonly PasswordHasher _hasher = new();
+ private static readonly Regex _md5Pattern =
+ new(@"^[0-9A-F]{32}$", RegexOptions.Compiled);
+
+ public static string HashPassword(string password)
+ {
+ if (string.IsNullOrEmpty(password)) return string.Empty;
+ return _hasher.HashPassword(string.Empty, password);
+ }
+
+ public static PasswordVerifyResult VerifyPassword(
+ string storedHash, string password)
+ {
+ if (string.IsNullOrEmpty(storedHash) ||
+ string.IsNullOrEmpty(password))
+ return PasswordVerifyResult.Failed;
+
+ if (IsLegacyMD5Hash(storedHash))
+ {
+ var md5 = ComputeMD5(password);
+ return string.Equals(storedHash, md5, StringComparison.Ordinal)
+ ? PasswordVerifyResult.SuccessRehashNeeded
+ : PasswordVerifyResult.Failed;
+ }
+
+ var result = _hasher.VerifyHashedPassword(
+ string.Empty, storedHash, password);
+ return result switch
+ {
+ PasswordVerificationResult.Success
+ => PasswordVerifyResult.Success,
+ PasswordVerificationResult.SuccessRehashNeeded
+ => PasswordVerifyResult.SuccessRehashNeeded,
+ _ => PasswordVerifyResult.Failed
+ };
+ }
+
+ public static bool IsLegacyMD5Hash(string hash)
+ {
+ if (string.IsNullOrEmpty(hash) || hash.Length != 32) return false;
+ return _md5Pattern.IsMatch(hash);
+ }
+
+ internal static string ComputeMD5(string input)
+ {
+ if (string.IsNullOrEmpty(input)) return string.Empty;
+ byte[] buffer = Encoding.UTF8.GetBytes(input);
+ byte[] hash = MD5.HashData(buffer);
+ var sb = new StringBuilder(32);
+ foreach (byte b in hash) sb.Append(b.ToString("X2"));
+ return sb.ToString();
+ }
+ }
+
+ public enum PasswordVerifyResult
+ {
+ Failed = 0,
+ Success = 1,
+ SuccessRehashNeeded = 2
+ }
+}
+```
+
+### Verify: `dotnet build src/WalkingTec.Mvvm.Core/ -c Release`
+
+### Commit message:
+```
+feat(security): add PasswordHashHelper with PBKDF2 and MD5 migration [P0-1a]
+Part of #3
+```
+
+---
+## Task 4: Apply Password Hashing to Existing Code [P0-1b]
+
+### 4a. File: `src/WalkingTec.Mvvm.Core/Utils.cs` (line ~757)
+
+Add [Obsolete] to GetMD5String:
+```csharp
+// FIND:
+ public static string GetMD5String(string str)
+// REPLACE WITH:
+ [Obsolete("Use PasswordHashHelper.HashPassword(). MD5 is broken for passwords.")]
+ public static string GetMD5String(string str)
+```
+
+Fix GetMD5Stream memory bomb (line ~775):
+```csharp
+// FIND entire method:
+ public static string GetMD5Stream(Stream stream)
+ {
+ byte[] buffer = new byte[stream.Length];
+ stream.Read(buffer, 0, buffer.Length);
+ return MD5String(buffer);
+ }
+// REPLACE WITH:
+ public static string GetMD5Stream(Stream stream)
+ {
+ using var md5 = MD5.Create();
+ byte[] hash = md5.ComputeHash(stream);
+ var sb = new StringBuilder(32);
+ foreach (byte b in hash)
+ sb.Append(b.ToString("X2"));
+ return sb.ToString();
+ }
+```
+
+### 4b. File: `src/WalkingTec.Mvvm.Core/WTMContext.cs` (line ~444-449)
+
+FIND (in else branch where IsAuthenticated is false):
+```csharp
+ else
+ {
+ exist = BaseUserQuery.IgnoreQueryFilters().Any(x => x.ITCode == username && x.Password == Utils.GetMD5String(password) && x.TenantCode == tenant && x.IsValid==true);
+ }
+```
+
+REPLACE WITH:
+```csharp
+ else
+ {
+ var userEntity = BaseUserQuery.IgnoreQueryFilters()
+ .Where(x => x.ITCode == username
+ && x.TenantCode == tenant
+ && x.IsValid == true)
+ .Select(x => new { x.ID, x.Password })
+ .FirstOrDefault();
+
+ if (userEntity != null)
+ {
+ var verifyResult = PasswordHashHelper.VerifyPassword(
+ userEntity.Password, password);
+
+ if (verifyResult == PasswordVerifyResult.Failed)
+ {
+ exist = false;
+ }
+ else
+ {
+ exist = true;
+ if (verifyResult == PasswordVerifyResult.SuccessRehashNeeded)
+ {
+ try
+ {
+ var newHash = PasswordHashHelper.HashPassword(password);
+ var dbUser = DC.Set()
+ .IgnoreQueryFilters()
+ .FirstOrDefault(x => x.ID == userEntity.ID);
+ if (dbUser != null)
+ {
+ dbUser.Password = newHash;
+ DC.SaveChanges();
+ }
+ }
+ catch { }
+ }
+ }
+ }
+ else
+ {
+ exist = false;
+ }
+ }
+```
+
+### 4c. Demo ViewModel Changes
+
+Run: `grep -rn "Utils.GetMD5String" demo/ --include="*.cs"` to find ALL occurrences.
+
+Standard replacement (apply to ALL demo projects - BlazorDemo, Demo, ReactDemo, Vue3Demo, VueDemo):
+
+| File pattern | Before | After |
+|---|---|---|
+| AccountController.cs | `Utils.GetMD5String(regInfo.Password)` | `PasswordHashHelper.HashPassword(regInfo.Password)` |
+| DataContext.cs | `Utils.GetMD5String("000000")` | `PasswordHashHelper.HashPassword("000000")` |
+| FrameworkTenantVM.cs | `Utils.GetMD5String("000000")` | `PasswordHashHelper.HashPassword("000000")` |
+| FrameworkUserImportVM.cs | `Utils.GetMD5String(item.Password)` | `PasswordHashHelper.HashPassword(item.Password)` |
+| FrameworkUserVM.cs (2x) | `Utils.GetMD5String(Entity.Password)` | `PasswordHashHelper.HashPassword(Entity.Password)` |
+
+Special: ChangePasswordVM.cs line ~32:
+```csharp
+// FIND:
+ if (DC.Set().Where(x => x.ITCode == LoginUserInfo.ITCode && x.Password == Utils.GetMD5String(OldPassword)).SingleOrDefault() == null)
+// REPLACE WITH:
+ var currentUser = DC.Set().Where(x => x.ITCode == LoginUserInfo.ITCode).SingleOrDefault();
+ if (currentUser == null || PasswordHashHelper.VerifyPassword(currentUser.Password, OldPassword) == PasswordVerifyResult.Failed)
+```
+
+ChangePasswordVM.cs line ~47:
+```csharp
+// FIND:
+ user.Password = Utils.GetMD5String(NewPassword);
+// REPLACE WITH:
+ user.Password = PasswordHashHelper.HashPassword(NewPassword);
+```
+
+### Verify: `dotnet build WalkingTec.Mvvm.sln -c Release && dotnet test WalkingTec.Mvvm.sln -c Release`
+
+### Commit message:
+```
+feat(security): apply PBKDF2 password hashing across codebase [P0-1b]
+Closes #3
+```
+
+---
+## Task 5: JWT Refresh Token [P0-2]
+
+### 5a. NEW FILE: `src/WalkingTec.Mvvm.Core/Models/RefreshTokenEntity.cs`
+
+```csharp
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace WalkingTec.Mvvm.Core
+{
+ [Table("FrameworkRefreshTokens")]
+ public class RefreshTokenEntity
+ {
+ [Key]
+ public Guid ID { get; set; } = Guid.NewGuid();
+ [Required, StringLength(256)]
+ public string Token { get; set; }
+ [Required, StringLength(50)]
+ public string ITCode { get; set; }
+ [StringLength(50)]
+ public string TenantCode { get; set; }
+ public DateTime ExpiresUtc { get; set; }
+ public DateTime CreatedUtc { get; set; } = DateTime.UtcNow;
+ [StringLength(50)]
+ public string CreatedByIp { get; set; }
+ public DateTime? RevokedUtc { get; set; }
+ [StringLength(50)]
+ public string RevokedByIp { get; set; }
+ [StringLength(256)]
+ public string ReplacedByToken { get; set; }
+ [StringLength(100)]
+ public string RevokeReason { get; set; }
+ [NotMapped]
+ public bool IsExpired => DateTime.UtcNow >= ExpiresUtc;
+ [NotMapped]
+ public bool IsRevoked => RevokedUtc != null;
+ [NotMapped]
+ public bool IsActive => !IsRevoked && !IsExpired;
+ }
+}
+```
+
+### 5b. REPLACE FILE: `src/WalkingTec.Mvvm.Core/Auth/ITokenService.cs`
+
+Note: The file might be at a different path. Search: `find src -name "ITokenService.cs" -not -path "*/obj/*"`
+
+```csharp
+using System.Threading.Tasks;
+using WalkingTec.Mvvm.Core.Support.Json;
+
+namespace WalkingTec.Mvvm.Core
+{
+ public interface ITokenService
+ {
+ Task IssueTokenAsync(LoginUserInfo loginUserInfo, string ipAddress = null);
+ Task RefreshTokenAsync(string refreshToken, string ipAddress = null);
+ Task RevokeTokenAsync(string refreshToken, string ipAddress = null, string reason = null);
+ }
+}
+```
+
+### 5c. REPLACE FILE: `src/WalkingTec.Mvvm.Mvc/Auth/JwtAuth/TokenService.cs`
+
+Full replacement file content is provided in the release package at `new-files/TokenService.cs`. The key changes are:
+- Constructor adds `IServiceProvider sp` parameter
+- `IssueTokenAsync` now creates and persists a RefreshTokenEntity
+- New `RefreshTokenAsync` with rotation and reuse detection
+- New `RevokeTokenAsync` for logout
+- `RefreshToken` field now returns actual cryptographic token instead of ""
+
+### 5d. Add DbSet to DataContext
+
+Find DataContext files: `grep -rn "DbSet" demo/ src/ --include="*.cs"`
+
+In each DataContext class, add:
+```csharp
+ public DbSet FrameworkRefreshTokens { get; set; }
+```
+
+### 5e. Add API endpoints to AccountController
+
+In each demo's AccountController (find: `grep -rn "loginjwt" demo/ --include="*.cs" -l`), add RefreshToken and RevokeToken endpoints. See release package for full code.
+
+### Verify: `dotnet build WalkingTec.Mvvm.sln -c Release`
+
+### Commit message:
+```
+feat(security): implement JWT refresh token with rotation [P0-2]
+Closes #4
+```
+
+---
+
+## Task 6: Async DoLogin [P1-3]
+
+Add `DoLoginAsync` to WTMContext.cs. It's identical to DoLogin but all `.Result` become `await` and all `.Wait()` become `await`.
+
+Keep existing `DoLogin` as deprecated wrapper:
+```csharp
+ [Obsolete("Use DoLoginAsync to avoid ThreadPool starvation.")]
+ public LoginUserInfo DoLogin(string username, string password, string tenant)
+ => DoLoginAsync(username, password, tenant).GetAwaiter().GetResult();
+```
+
+Update all callers: `grep -rn "\.DoLogin(" demo/ src/ --include="*.cs"` - change to `await Wtm.DoLoginAsync(...)`.
+
+### Commit message:
+```
+perf: convert DoLogin to async [P1-3]
+Closes #5
+```
+
+---
+
+## Task 7: CI Pipeline
+
+### NEW FILE: `.github/workflows/ci-build.yml`
+
+```yaml
+name: WTM Build and Test
+on:
+ push:
+ branches: [ dotnet8, "feature/**" ]
+ pull_request:
+ branches: [ dotnet8 ]
+env:
+ DOTNET_VERSION: '8.0.x'
+ SOLUTION_FILE: 'WalkingTec.Mvvm.sln'
+jobs:
+ build-and-test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0.x
+ - run: dotnet restore WalkingTec.Mvvm.sln
+ - run: dotnet build WalkingTec.Mvvm.sln --no-restore -c Release
+ - run: dotnet test WalkingTec.Mvvm.sln --no-build -c Release --verbosity normal
+ security-scan:
+ runs-on: ubuntu-latest
+ needs: build-and-test
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0.x
+ - run: dotnet list WalkingTec.Mvvm.sln package --vulnerable --include-transitive
+```
+
+### Commit: `ci: add GitHub Actions workflow`
+
+---
+
+## DB Migration (run BEFORE deploying code)
+
+```sql
+ALTER TABLE [FrameworkUser] ALTER COLUMN [Password] NVARCHAR(256) NOT NULL;
+
+CREATE TABLE [FrameworkRefreshTokens] (
+ [ID] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT NEWID(),
+ [Token] NVARCHAR(256) NOT NULL,
+ [ITCode] NVARCHAR(50) NOT NULL,
+ [TenantCode] NVARCHAR(50) NULL,
+ [ExpiresUtc] DATETIME2 NOT NULL,
+ [CreatedUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
+ [CreatedByIp] NVARCHAR(50) NULL,
+ [RevokedUtc] DATETIME2 NULL,
+ [RevokedByIp] NVARCHAR(50) NULL,
+ [ReplacedByToken] NVARCHAR(256) NULL,
+ [RevokeReason] NVARCHAR(100) NULL
+);
+CREATE INDEX IX_RefreshToken_Token ON [FrameworkRefreshTokens]([Token]);
+CREATE INDEX IX_RefreshToken_ITCode ON [FrameworkRefreshTokens]([ITCode]);
+```
+
+## Final: Push, PR, Merge
+
+```bash
+git push origin feature/8.1.13-security
+gh pr create --base dotnet8 --title "v8.1.13: P0/P1 Security Patches" --body "Closes #1 #2 #3 #4 #5"
+# Wait for CI green
+gh pr merge --squash
+git checkout dotnet8 && git pull
+git tag -a v8.1.13 -m "Security: PBKDF2 passwords, JWT refresh, legacy deps, async login"
+git push origin v8.1.13
+```
diff --git a/WTM-8.1.14-SPEC.md b/WTM-8.1.14-SPEC.md
new file mode 100644
index 000000000..0472d56e0
--- /dev/null
+++ b/WTM-8.1.14-SPEC.md
@@ -0,0 +1,745 @@
+# WTM 8.1.14 Technical Debt & Stabilization - Claude CLI Execution Spec
+
+## Overview
+
+This document is the **single source of truth** for v8.1.14 technical debt cleanup on the WTM fork (`cct08311github/WTM`, `dotnet8` branch). Designed for Claude CLI automated execution.
+
+**Repository:** https://github.com/cct08311github/WTM
+**Branch:** `dotnet8` (base after v8.1.13 merged), create `feature/8.1.14-stabilize` for work
+**Prerequisite:** v8.1.13 must be merged into `dotnet8` first
+**Current version:** WTM 8.1.13, targeting net8.0
+
+---
+
+## Execution Order (6 tasks, each = 1 git commit)
+
+| Task | ID | Priority | Type | Risk |
+|------|----|----------|------|------|
+| 1 | ASYNC-1 | HIGH | Code modification (multiple files) | Medium |
+| 2 | DEPS-1 | HIGH | Dependency updates | Medium |
+| 3 | QUALITY-1 | MEDIUM | New file (.editorconfig) | Low |
+| 4 | QUALITY-2 | MEDIUM | csproj modifications | Low-Medium |
+| 5 | TEST-1 | MEDIUM | New project + test files | Low |
+| 6 | CI-UPDATE | LOW | CI config update | Low |
+
+Before starting:
+```bash
+git checkout dotnet8 && git pull origin dotnet8
+git checkout -b feature/8.1.14-stabilize
+dotnet build WalkingTec.Mvvm.sln -c Release # confirm baseline
+```
+
+---
+## GitHub Issues to Create (4 total, create ALL before starting code changes)
+
+### Issue #6
+```
+Title: [P1-3 cont.] Complete sync-over-async fixes across codebase
+Labels: performance, P1
+```
+Body:
+v8.1.13 fixed DoLogin. Remaining ~15 `.Result/.Wait()` calls cause ThreadPool starvation risk under load.
+
+Locations:
+- `_WorkflowApiController.cs`: 5x `Request.RedirectCall(...).Result`
+- `ApproveActivity.cs`: 5x `CallAPI(...).Result`
+- `FrameworkServiceExtension.cs`: `DataInit(...).Wait()`
+- `SessionExtension.cs`: `CommitAsync().Wait()`
+- Any others found via `grep -rn "\.Result[^s]" src/ --include="*.cs"` and `grep -rn "\.Wait()" src/ --include="*.cs"`
+
+Fix: Convert to async/await. Keep sync wrappers marked [Obsolete] where public API.
+Risk: Medium | Effort: 2-3 days
+
+### Issue #7
+```
+Title: [DEPS] Full dependency audit and update
+Labels: dependencies, security
+```
+Body:
+Run `dotnet list WalkingTec.Mvvm.sln package --outdated` and upgrade all packages to latest stable within same major version. Do NOT cross major version boundaries without explicit approval.
+
+Special attention:
+- EF Core: upgrade to latest 8.0.x patch
+- System.Text.Json: check version alignment
+- Any package with known CVEs (check `dotnet list package --vulnerable`)
+
+Risk: Medium | Effort: 1 day
+
+### Issue #8
+```
+Title: [QUALITY] Add .editorconfig and enable Nullable Reference Types
+Labels: quality, code-health
+```
+Body:
+1. Add `.editorconfig` with consistent C# coding standards
+2. Enable `enable` starting with Core project
+3. Fix resulting warnings (nullable annotations)
+
+Risk: Low-Medium | Effort: 2-3 days
+
+### Issue #9
+```
+Title: [TEST] Establish unit test project and baseline coverage
+Labels: testing, quality
+```
+Body:
+Create xUnit test project targeting critical security code:
+- PasswordHashHelper (hash, verify, MD5 migration)
+- TokenService (issue, refresh, revoke, reuse detection)
+- RefreshTokenEntity (computed properties)
+
+Goal: baseline test coverage on security-critical paths.
+Risk: Low | Effort: 2 days
+
+---
+## Task 1: Complete Sync-over-Async Fixes [ASYNC-1]
+
+### Step 1: Full scan of remaining violations
+
+Run these commands to find ALL remaining sync-over-async:
+```bash
+# Find .Result calls (excluding comments, string literals, test files)
+grep -rn "\.Result[^s\"]" src/ --include="*.cs" | grep -v "//.*\.Result" | grep -v "/obj/"
+
+# Find .Wait() calls
+grep -rn "\.Wait()" src/ --include="*.cs" | grep -v "//.*\.Wait" | grep -v "/obj/"
+
+# Find .GetAwaiter().GetResult() calls (these are OK in [Obsolete] wrappers only)
+grep -rn "GetAwaiter().GetResult()" src/ --include="*.cs" | grep -v "/obj/"
+```
+
+### Step 2: Fix `_WorkflowApiController`
+
+File: Search with `find src/ -name "*Workflow*" -not -path "*/obj/*"`
+(Note: This might be a .txt template file that generates controllers)
+
+For each occurrence of `.Result`:
+```csharp
+// FIND pattern:
+var result = someAsyncCall(...).Result;
+// REPLACE WITH:
+var result = await someAsyncCall(...);
+```
+
+Ensure the containing method signature is changed to `async Task` if not already.
+
+### Step 3: Fix `ApproveActivity.cs`
+
+File: Search with `find src/ -name "ApproveActivity.cs" -not -path "*/obj/*"`
+
+Same pattern: replace all `.Result` with `await`, change method signatures to async.
+
+### Step 4: Fix `FrameworkServiceExtension.cs`
+
+File: Search with `find src/ -name "FrameworkServiceExtension.cs" -not -path "*/obj/*"`
+
+```csharp
+// FIND pattern:
+DataInit(...).Wait();
+// REPLACE WITH:
+await DataInit(...);
+```
+
+If `DataInit` is called from a synchronous context (like `Configure`), use this pattern instead:
+```csharp
+// If in IApplicationBuilder pipeline (sync context), keep as-is but add comment:
+// TODO: Convert to IHostedService for proper async startup in future version
+DataInit(...).GetAwaiter().GetResult();
+```
+
+### Step 5: Fix `SessionExtension.cs`
+
+File: Search with `find src/ -name "SessionExtension.cs" -not -path "*/obj/*"`
+
+```csharp
+// FIND pattern:
+CommitAsync().Wait();
+// REPLACE WITH (if method can be made async):
+await CommitAsync();
+// OR (if sync context is unavoidable):
+// Add [Obsolete] and provide async alternative
+```
+
+### Step 6: Fix any remaining violations found in Step 1
+
+Apply the same patterns. For each file:
+1. If the caller can be made async -> use await
+2. If the caller is in a sync-only context (startup, interface constraint) -> use `.GetAwaiter().GetResult()` with a `// TODO` comment
+3. Never use `.Result` or `.Wait()` - these can deadlock
+
+### Verification
+```bash
+dotnet build WalkingTec.Mvvm.sln -c Release
+
+# Verify no remaining .Result/.Wait() (except [Obsolete] wrappers and startup code):
+grep -rn "\.Result[^s\"]" src/ --include="*.cs" | grep -v "/obj/" | grep -v "Obsolete" | grep -v "TODO"
+grep -rn "\.Wait()" src/ --include="*.cs" | grep -v "/obj/" | grep -v "Obsolete" | grep -v "TODO"
+```
+
+### Commit message:
+```
+perf: complete sync-over-async fixes across codebase [ASYNC-1]
+
+- WorkflowApiController: convert RedirectCall().Result to await
+- ApproveActivity: convert CallAPI().Result to await
+- FrameworkServiceExtension: fix DataInit().Wait()
+- SessionExtension: fix CommitAsync().Wait()
+- Mark unavoidable sync wrappers with TODO for future refactor
+
+Closes #6
+```
+
+---
+## Task 2: Full Dependency Audit and Update [DEPS-1]
+
+### Step 1: Audit current state
+
+```bash
+# List all outdated packages
+dotnet list WalkingTec.Mvvm.sln package --outdated
+
+# Check for known vulnerabilities
+dotnet list WalkingTec.Mvvm.sln package --vulnerable --include-transitive
+```
+
+### Step 2: Upgrade rules
+
+**DO upgrade:**
+- All packages within same major version to latest patch/minor
+- EF Core 8.x -> latest 8.0.x
+- Microsoft.Extensions.* -> latest 8.x
+- Any package with CVE advisories
+
+**DO NOT upgrade without asking the project owner:**
+- Any package crossing a major version boundary (e.g., 7.x -> 8.x, 2.x -> 3.x)
+- Newtonsoft.Json (deep integration, needs separate migration plan)
+
+**DO NOT upgrade at all:**
+- Packages that would require .NET 9 (skip per project owner decision)
+
+### Step 3: Apply upgrades
+
+For each `.csproj` file with outdated packages, update the version number.
+
+After EACH package group upgrade, run:
+```bash
+dotnet build WalkingTec.Mvvm.sln -c Release
+```
+
+If build fails after a specific upgrade, revert that one and note it as a known issue.
+
+### Step 4: Verify no new vulnerabilities
+```bash
+dotnet list WalkingTec.Mvvm.sln package --vulnerable --include-transitive
+```
+
+### Commit message:
+```
+fix(deps): full dependency audit and update to latest stable [DEPS-1]
+
+- Upgraded [list each package: name X.Y.Z -> X.Y.Z]
+- No major version boundary crossings
+- Verified zero known CVEs in direct dependencies
+
+Closes #7
+```
+
+---
+## Task 3: Add .editorconfig [QUALITY-1]
+
+### NEW FILE: `.editorconfig` (in repo root)
+
+```ini
+# EditorConfig: https://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.{json,yml,yaml}]
+indent_size = 2
+
+[*.{csproj,props,targets}]
+indent_size = 2
+
+[*.cs]
+# Namespace
+dotnet_style_namespace_match_folder = true
+
+# Using directives
+dotnet_sort_system_directives_first = true
+dotnet_separate_import_directive_groups = false
+
+# this. qualification
+dotnet_style_qualification_for_field = false:suggestion
+dotnet_style_qualification_for_property = false:suggestion
+dotnet_style_qualification_for_method = false:suggestion
+dotnet_style_qualification_for_event = false:suggestion
+
+# Language keywords vs BCL types
+dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
+dotnet_style_predefined_type_for_member_access = true:suggestion
+
+# var preferences
+csharp_style_var_for_built_in_types = false:suggestion
+csharp_style_var_when_type_is_apparent = true:suggestion
+csharp_style_var_elsewhere = false:suggestion
+
+# Expression-level preferences
+csharp_style_expression_bodied_methods = when_on_single_line:suggestion
+csharp_style_expression_bodied_constructors = false:suggestion
+csharp_style_expression_bodied_properties = true:suggestion
+csharp_style_expression_bodied_accessors = true:suggestion
+
+# Pattern matching
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+
+# Null checking
+csharp_style_throw_expression = true:suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+
+# Formatting
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_space_after_cast = false
+csharp_space_after_keywords_in_control_flow_statements = true
+
+# Naming conventions
+dotnet_naming_rule.private_fields_should_be_camel_case.severity = suggestion
+dotnet_naming_rule.private_fields_should_be_camel_case.symbols = private_fields
+dotnet_naming_rule.private_fields_should_be_camel_case.style = camel_case_prefix
+
+dotnet_naming_symbols.private_fields.applicable_kinds = field
+dotnet_naming_symbols.private_fields.applicable_accessibilities = private
+
+dotnet_naming_style.camel_case_prefix.capitalization = camel_case
+dotnet_naming_style.camel_case_prefix.required_prefix = _
+
+# Severity overrides - don't break build for style
+dotnet_analyzer_diagnostic.category-Style.severity = suggestion
+```
+
+### Verification
+```bash
+dotnet build WalkingTec.Mvvm.sln -c Release
+# Should produce no new errors (style rules are suggestion level only)
+```
+
+### Commit message:
+```
+chore: add .editorconfig with C# coding standards [QUALITY-1]
+
+- Consistent indentation, charset, line endings
+- C# style rules as suggestions (non-breaking)
+- Naming conventions for private fields (_camelCase)
+
+Part of #8
+```
+
+---
+## Task 4: Enable Nullable Reference Types [QUALITY-2]
+
+### Strategy: Incremental enablement
+
+Enable Nullable in this order (least to most dependents):
+1. `WalkingTec.Mvvm.Core` - the foundation
+2. Only Core for v8.1.14. Other projects in future versions.
+
+### Step 1: Enable in Core.csproj
+
+File: `src/WalkingTec.Mvvm.Core/WalkingTec.Mvvm.Core.csproj`
+
+ADD inside ``:
+```xml
+ enable
+```
+
+### Step 2: Build and assess
+
+```bash
+dotnet build src/WalkingTec.Mvvm.Core/ -c Release 2>&1 | grep -c "warning CS86"
+```
+
+This will show the count of nullable warnings.
+
+### Step 3: Fix warnings - priority tiers
+
+**Tier 1 - Fix immediately (security-critical files from v8.1.13):**
+- `PasswordHashHelper.cs` - add proper null annotations
+- `RefreshTokenEntity.cs` - mark nullable properties with `?`
+- `ITokenService.cs` - annotate return types
+
+**Tier 2 - Fix if < 50 warnings:**
+- Model classes: add `?` to optional properties, `required` to mandatory ones
+- Extension methods: add null guards
+
+**Tier 3 - Suppress if > 50 warnings remaining:**
+For files that would take excessive effort, add at the top of the file:
+```csharp
+#nullable disable
+```
+This preserves the opt-in model without blocking the build.
+
+### Step 4: Ensure zero warnings in new code
+
+After fixing/suppressing, the build must be clean:
+```bash
+dotnet build WalkingTec.Mvvm.sln -c Release
+# Full solution must still build. Nullable warnings are OK in non-Core projects.
+# Core project should have zero nullable warnings.
+```
+
+### Important: Do NOT enable Nullable in other projects yet
+Projects that depend on Core will get warnings from consuming nullable-annotated APIs. That is fine - they will be addressed in future versions.
+
+### Commit message:
+```
+chore: enable Nullable Reference Types in Core project [QUALITY-2]
+
+- Enable enable in WalkingTec.Mvvm.Core.csproj
+- Add null annotations to security-critical files
+- Suppress nullable in legacy files pending future cleanup
+- Other projects remain nullable-oblivious for now
+
+Closes #8
+```
+
+---
+## Task 5: Establish Unit Test Project [TEST-1]
+
+### Step 1: Create test project
+
+```bash
+cd src/
+dotnet new xunit -n WalkingTec.Mvvm.Core.Tests -f net8.0
+cd WalkingTec.Mvvm.Core.Tests/
+dotnet add reference ../WalkingTec.Mvvm.Core/WalkingTec.Mvvm.Core.csproj
+dotnet add package Moq --version 4.*
+dotnet add package FluentAssertions --version 6.*
+dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 8.*
+```
+
+### Step 2: Add test project to solution
+
+```bash
+cd ../../ # back to repo root
+dotnet sln WalkingTec.Mvvm.sln add src/WalkingTec.Mvvm.Core.Tests/WalkingTec.Mvvm.Core.Tests.csproj
+```
+
+### Step 3: Add InternalsVisibleTo in Core.csproj
+
+File: `src/WalkingTec.Mvvm.Core/WalkingTec.Mvvm.Core.csproj`
+
+ADD this ItemGroup:
+```xml
+
+
+
+```
+
+### Step 4: Create test files
+
+#### NEW FILE: `src/WalkingTec.Mvvm.Core.Tests/PasswordHashHelperTests.cs`
+
+```csharp
+using FluentAssertions;
+using WalkingTec.Mvvm.Core;
+using Xunit;
+
+namespace WalkingTec.Mvvm.Core.Tests
+{
+ public class PasswordHashHelperTests
+ {
+ [Fact]
+ public void HashPassword_ReturnsNonEmptyString()
+ {
+ var hash = PasswordHashHelper.HashPassword("test123");
+ hash.Should().NotBeNullOrEmpty();
+ hash.Should().NotBe("test123");
+ }
+
+ [Fact]
+ public void HashPassword_EmptyInput_ReturnsEmpty()
+ {
+ PasswordHashHelper.HashPassword("").Should().BeEmpty();
+ PasswordHashHelper.HashPassword(null).Should().BeEmpty();
+ }
+
+ [Fact]
+ public void HashPassword_DifferentCalls_ProduceDifferentHashes()
+ {
+ var hash1 = PasswordHashHelper.HashPassword("test123");
+ var hash2 = PasswordHashHelper.HashPassword("test123");
+ hash1.Should().NotBe(hash2, "PBKDF2 uses random salt");
+ }
+
+ [Fact]
+ public void VerifyPassword_CorrectPassword_ReturnsSuccess()
+ {
+ var hash = PasswordHashHelper.HashPassword("myPassword");
+ var result = PasswordHashHelper.VerifyPassword(hash, "myPassword");
+ result.Should().Be(PasswordVerifyResult.Success);
+ }
+
+ [Fact]
+ public void VerifyPassword_WrongPassword_ReturnsFailed()
+ {
+ var hash = PasswordHashHelper.HashPassword("myPassword");
+ var result = PasswordHashHelper.VerifyPassword(hash, "wrongPassword");
+ result.Should().Be(PasswordVerifyResult.Failed);
+ }
+
+ [Fact]
+ public void VerifyPassword_NullInputs_ReturnsFailed()
+ {
+ PasswordHashHelper.VerifyPassword(null, "pw")
+ .Should().Be(PasswordVerifyResult.Failed);
+ PasswordHashHelper.VerifyPassword("hash", null)
+ .Should().Be(PasswordVerifyResult.Failed);
+ PasswordHashHelper.VerifyPassword(null, null)
+ .Should().Be(PasswordVerifyResult.Failed);
+ }
+
+ [Fact]
+ public void VerifyPassword_LegacyMD5_ReturnsSuccessRehashNeeded()
+ {
+ var md5Hash = PasswordHashHelper.ComputeMD5("000000");
+ var result = PasswordHashHelper.VerifyPassword(md5Hash, "000000");
+ result.Should().Be(PasswordVerifyResult.SuccessRehashNeeded);
+ }
+
+ [Fact]
+ public void VerifyPassword_LegacyMD5_WrongPassword_ReturnsFailed()
+ {
+ var md5Hash = PasswordHashHelper.ComputeMD5("000000");
+ var result = PasswordHashHelper.VerifyPassword(md5Hash, "111111");
+ result.Should().Be(PasswordVerifyResult.Failed);
+ }
+
+ [Fact]
+ public void IsLegacyMD5Hash_ValidMD5_ReturnsTrue()
+ {
+ PasswordHashHelper.IsLegacyMD5Hash("670B14728AD9902AECBA32E22FA4F6BD")
+ .Should().BeTrue();
+ }
+
+ [Fact]
+ public void IsLegacyMD5Hash_PBKDF2Hash_ReturnsFalse()
+ {
+ var pbkdf2 = PasswordHashHelper.HashPassword("test");
+ PasswordHashHelper.IsLegacyMD5Hash(pbkdf2).Should().BeFalse();
+ }
+
+ [Fact]
+ public void IsLegacyMD5Hash_NullOrEmpty_ReturnsFalse()
+ {
+ PasswordHashHelper.IsLegacyMD5Hash(null).Should().BeFalse();
+ PasswordHashHelper.IsLegacyMD5Hash("").Should().BeFalse();
+ }
+
+ [Fact]
+ public void IsLegacyMD5Hash_WrongLength_ReturnsFalse()
+ {
+ PasswordHashHelper.IsLegacyMD5Hash("ABC123").Should().BeFalse();
+ }
+
+ [Fact]
+ public void MigrationFlow_MD5ToNewHash_Verify_Success()
+ {
+ // Simulate: user had MD5 password, logs in, system upgrades
+ var legacyMD5 = PasswordHashHelper.ComputeMD5("secretPassword");
+
+ // Step 1: Verify against legacy hash
+ var verifyResult = PasswordHashHelper.VerifyPassword(
+ legacyMD5, "secretPassword");
+ verifyResult.Should().Be(PasswordVerifyResult.SuccessRehashNeeded);
+
+ // Step 2: Generate new PBKDF2 hash
+ var newHash = PasswordHashHelper.HashPassword("secretPassword");
+
+ // Step 3: Verify against new hash
+ var verifyNew = PasswordHashHelper.VerifyPassword(
+ newHash, "secretPassword");
+ verifyNew.Should().Be(PasswordVerifyResult.Success);
+ }
+ }
+}
+```
+
+#### NEW FILE: `src/WalkingTec.Mvvm.Core.Tests/RefreshTokenEntityTests.cs`
+
+```csharp
+using System;
+using FluentAssertions;
+using WalkingTec.Mvvm.Core;
+using Xunit;
+
+namespace WalkingTec.Mvvm.Core.Tests
+{
+ public class RefreshTokenEntityTests
+ {
+ [Fact]
+ public void NewToken_IsActive()
+ {
+ var token = new RefreshTokenEntity
+ {
+ Token = "test-token",
+ ITCode = "admin",
+ ExpiresUtc = DateTime.UtcNow.AddDays(7)
+ };
+ token.IsActive.Should().BeTrue();
+ token.IsExpired.Should().BeFalse();
+ token.IsRevoked.Should().BeFalse();
+ }
+
+ [Fact]
+ public void ExpiredToken_IsNotActive()
+ {
+ var token = new RefreshTokenEntity
+ {
+ Token = "test-token",
+ ITCode = "admin",
+ ExpiresUtc = DateTime.UtcNow.AddMinutes(-1)
+ };
+ token.IsActive.Should().BeFalse();
+ token.IsExpired.Should().BeTrue();
+ }
+
+ [Fact]
+ public void RevokedToken_IsNotActive()
+ {
+ var token = new RefreshTokenEntity
+ {
+ Token = "test-token",
+ ITCode = "admin",
+ ExpiresUtc = DateTime.UtcNow.AddDays(7),
+ RevokedUtc = DateTime.UtcNow
+ };
+ token.IsActive.Should().BeFalse();
+ token.IsRevoked.Should().BeTrue();
+ }
+
+ [Fact]
+ public void NewToken_HasGeneratedID()
+ {
+ var token = new RefreshTokenEntity();
+ token.ID.Should().NotBe(Guid.Empty);
+ }
+
+ [Fact]
+ public void NewToken_HasCreatedUtcSet()
+ {
+ var before = DateTime.UtcNow.AddSeconds(-1);
+ var token = new RefreshTokenEntity();
+ var after = DateTime.UtcNow.AddSeconds(1);
+ token.CreatedUtc.Should().BeAfter(before).And.BeBefore(after);
+ }
+ }
+}
+```
+
+### Verification
+```bash
+dotnet build WalkingTec.Mvvm.sln -c Release
+dotnet test src/WalkingTec.Mvvm.Core.Tests/ -c Release --verbosity normal
+```
+
+All tests must pass. Expected: 17+ tests, 0 failures.
+
+### Commit message:
+```
+test: add unit test project with PasswordHashHelper and RefreshToken tests [TEST-1]
+
+- New xUnit project: WalkingTec.Mvvm.Core.Tests
+- 12 tests for PasswordHashHelper (hash, verify, MD5 migration flow)
+- 5 tests for RefreshTokenEntity (active/expired/revoked states)
+- Dependencies: FluentAssertions, Moq, EF Core InMemory
+- Added InternalsVisibleTo for testing internal methods
+
+Closes #9
+```
+
+---
+## Task 6: Update CI Pipeline [CI-UPDATE]
+
+### File: `.github/workflows/ci-build.yml`
+
+UPDATE the test step to include test result artifact upload.
+
+FIND:
+```yaml
+ - run: dotnet test WalkingTec.Mvvm.sln --no-build -c Release --verbosity normal
+```
+REPLACE WITH:
+```yaml
+ - name: Test
+ run: dotnet test WalkingTec.Mvvm.sln --no-build -c Release --verbosity normal --logger "trx;LogFileName=test-results.trx"
+
+ - name: Upload test results
+ uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: test-results
+ path: "**/test-results.trx"
+```
+
+### Commit message:
+```
+ci: update workflow with test result artifacts [CI-UPDATE]
+```
+
+---
+
+## Final Steps After All Tasks Complete
+
+```bash
+# Push feature branch
+git push origin feature/8.1.14-stabilize
+
+# Create PR
+gh pr create \
+ --base dotnet8 \
+ --title "v8.1.14: Technical Debt Cleanup & Stabilization" \
+ --body "## Changes
+- Complete sync-over-async fixes (remaining .Result/.Wait() removed)
+- Full dependency audit and update
+- .editorconfig with C# coding standards
+- Nullable Reference Types enabled in Core project
+- Unit test project with baseline tests on security-critical code
+
+Closes #6 #7 #8 #9"
+
+# After CI passes and owner confirms, merge
+gh pr merge --squash
+
+# Tag release
+git checkout dotnet8 && git pull
+git tag -a v8.1.14 -m "Stabilization: async fixes, dep updates, nullable, unit tests"
+git push origin v8.1.14
+```
+
+---
+
+## Notes for Claude CLI Execution
+
+1. **Task 1 (async)** is the most complex - search carefully. Some `.Result` calls are in template `.txt` files that generate controllers. Fix those too.
+2. **Task 2 (deps)** - run the audit commands first, then TELL the project owner what you plan to upgrade before doing it. Do NOT upgrade across major versions. Do NOT upgrade to anything requiring .NET 9.
+3. **Task 4 (nullable)** - if warnings exceed 100 in Core project, use `#nullable disable` at the top of the worst files and note them for future cleanup. Do NOT let nullable warnings break the build.
+4. **Task 5 (tests)** - the `ComputeMD5` method is `internal`, so the test project needs `InternalsVisibleTo`. This is handled in Step 3.
+5. Do NOT merge PR automatically - wait for project owner confirmation.
+6. If any task fails to build, STOP and report. Do not attempt speculative fixes.
diff --git a/WalkingTec.Mvvm.sln b/WalkingTec.Mvvm.sln
index 9d4ca04b7..de29b2732 100644
--- a/WalkingTec.Mvvm.sln
+++ b/WalkingTec.Mvvm.sln
@@ -59,6 +59,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WalkingTec.Mvvm.BlazorDemo.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WalkingTec.Mvvm.Vue3Demo", "demo\WalkingTec.Mvvm.Vue3Demo\WalkingTec.Mvvm.Vue3Demo.csproj", "{411690A4-0021-4509-BF24-900437B5DC6E}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WalkingTec.Mvvm.Core.Tests", "src\WalkingTec.Mvvm.Core.Tests\WalkingTec.Mvvm.Core.Tests.csproj", "{7338D82E-C258-4739-AE85-3B8B0D27AAED}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -133,6 +135,10 @@ Global
{411690A4-0021-4509-BF24-900437B5DC6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{411690A4-0021-4509-BF24-900437B5DC6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{411690A4-0021-4509-BF24-900437B5DC6E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7338D82E-C258-4739-AE85-3B8B0D27AAED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7338D82E-C258-4739-AE85-3B8B0D27AAED}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7338D82E-C258-4739-AE85-3B8B0D27AAED}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7338D82E-C258-4739-AE85-3B8B0D27AAED}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -156,6 +162,7 @@ Global
{94352C3E-899A-44A2-A052-578DC6A7159F} = {840C6DED-B5D5-4763-A6A7-6F615B72EC10}
{D4104589-85BE-446A-A123-1E0FD1538A7B} = {840C6DED-B5D5-4763-A6A7-6F615B72EC10}
{411690A4-0021-4509-BF24-900437B5DC6E} = {DE184A47-CF5F-41C0-AB7D-CAD0AF2DAE75}
+ {7338D82E-C258-4739-AE85-3B8B0D27AAED} = {46CFCDC6-4358-48EB-A901-5618B6530CEE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8D25EAAD-E43A-466A-95DA-ECE1F3C462DC}
diff --git a/claude-cli-prompt-8.1.14.md b/claude-cli-prompt-8.1.14.md
new file mode 100644
index 000000000..72656951d
--- /dev/null
+++ b/claude-cli-prompt-8.1.14.md
@@ -0,0 +1,39 @@
+# WTM 8.1.14 Claude CLI Startup Prompt
+
+Place WTM-8.1.14-SPEC.md in repo root, then start claude and paste this prompt:
+
+---
+
+You are the senior .NET maintenance engineer for the WTM framework fork.
+Execute the WTM 8.1.14 stabilization spec from WTM-8.1.14-SPEC.md in this repo.
+
+Rules:
+1. Read WTM-8.1.14-SPEC.md first with cat WTM-8.1.14-SPEC.md
+2. Execute Task 1 through 6 strictly in order
+3. Each Task = 1 git commit with the exact commit message from the spec
+4. dotnet build after every Task
+5. If build fails, STOP and show me the error. Do not guess.
+6. For Task 2 (deps): show me the upgrade plan BEFORE applying it
+
+Phase 0: Prerequisites
+- Confirm v8.1.13 is merged: git log --oneline -5 dotnet8
+- git checkout dotnet8 && git pull origin dotnet8
+- git checkout -b feature/8.1.14-stabilize
+- dotnet build WalkingTec.Mvvm.sln -c Release (baseline check)
+
+Phase 1: Create GitHub Issues #6 through #9 using gh issue create
+
+Phase 2: Execute Tasks 1-6 following the spec exactly
+- Task 1: grep ALL .Result/.Wait() first, fix systematically
+- Task 2: show upgrade plan, wait for my OK, then apply
+- Task 3: create .editorconfig exactly as specified
+- Task 4: enable Nullable in Core only, use #nullable disable for noisy legacy files
+- Task 5: create xUnit project, add InternalsVisibleTo, write tests, run tests
+- Task 6: update CI yaml
+
+Phase 3: Push and PR
+- git push origin feature/8.1.14-stabilize
+- Create PR targeting dotnet8
+- Do NOT merge. Wait for my confirmation.
+
+Start now. Phase 0 first, report baseline build status.
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.Shared/WtmBlazorUtils/BasePage.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.Shared/WtmBlazorUtils/BasePage.cs
index 89016ecd6..a64efcd3a 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.Shared/WtmBlazorUtils/BasePage.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.Shared/WtmBlazorUtils/BasePage.cs
@@ -529,21 +529,21 @@ public string GetServerUrl()
}
}
- public Task>> DefaultTreeConverter(IEnumerable data) where T:TreePoco
+ public async Task>> DefaultTreeConverter(IEnumerable data) where T:TreePoco
{
List> rv = new List>();
if(data == null || data.Count() == 0)
{
- return Task.FromResult(rv.AsEnumerable());
+ return rv.AsEnumerable();
}
foreach (var item in data)
{
TableTreeNode tt = new TableTreeNode(item);
tt.HasChildren = item.HasChildren;
- tt.Items = DefaultTreeConverter(item.Children).Result;
+ tt.Items = await DefaultTreeConverter(item.Children);
rv.Add(tt);
}
- return Task.FromResult(rv.AsEnumerable());
+ return rv.AsEnumerable();
}
}
}
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/DataPrivilegeVMs/DataPrivilegeListVM.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/DataPrivilegeVMs/DataPrivilegeListVM.cs
index 6b9464eac..8af432d81 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/DataPrivilegeVMs/DataPrivilegeListVM.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/DataPrivilegeVMs/DataPrivilegeListVM.cs
@@ -130,7 +130,7 @@ public override void AfterDoSearcher()
Dictionary groupdata = new Dictionary();
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- var dd = Wtm.CallAPI>("mainhost", "/api/_account/GetFrameworkGroups").Result;
+ var dd = Wtm.CallAPI>("mainhost", "/api/_account/GetFrameworkGroups").GetAwaiter().GetResult();
if(dd.Data != null)
{
foreach (var item in dd.Data)
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/DataPrivilegeVMs/DataPrivilegeVM.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/DataPrivilegeVMs/DataPrivilegeVM.cs
index aa3564868..e7ecde6ef 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/DataPrivilegeVMs/DataPrivilegeVM.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/DataPrivilegeVMs/DataPrivilegeVM.cs
@@ -77,7 +77,7 @@ public override void Validate()
string user = null;
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- var check = Wtm.CallAPI>("mainhost", "/api/_account/GetUserById").Result;
+ var check = Wtm.CallAPI>("mainhost", "/api/_account/GetUserById").GetAwaiter().GetResult();
if (check.Data != null)
{
user = check.Data.Where(x => x.Value.ToString() == Entity.UserCode).Select(x => x.Value.ToString()).FirstOrDefault();
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkGroupVMs/FrameworkGroupVM.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkGroupVMs/FrameworkGroupVM.cs
index 30326329f..0a7a93357 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkGroupVMs/FrameworkGroupVM.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkGroupVMs/FrameworkGroupVM.cs
@@ -34,13 +34,13 @@ public override void Validate()
public override void DoAdd()
{
base.DoAdd();
- Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override void DoEdit(bool updateAllFields = false)
{
base.DoEdit(updateAllFields);
- Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override async Task DoDeleteAsync()
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkMenuVMs/FrameworkMenuVM2.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkMenuVMs/FrameworkMenuVM2.cs
index 3550ccff2..9602caa94 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkMenuVMs/FrameworkMenuVM2.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkMenuVMs/FrameworkMenuVM2.cs
@@ -269,7 +269,7 @@ public void AddPrivilege(List menuids)
}
}
DC.SaveChanges();
- Wtm.RemoveUserCacheByRole(SelectedRolesCodes.ToArray()).Wait();
+ Wtm.RemoveUserCacheByRole(SelectedRolesCodes.ToArray()).GetAwaiter().GetResult();
}
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkRoleVMs/FrameworkRoleMDVM2.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkRoleVMs/FrameworkRoleMDVM2.cs
index b79eb180a..db256d4ad 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkRoleVMs/FrameworkRoleMDVM2.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkRoleVMs/FrameworkRoleMDVM2.cs
@@ -24,7 +24,7 @@ protected override FrameworkRole GetById(object Id)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Wtm.CallAPI("mainhost", $"/api/_frameworkrole/{Id}").Result.Data.Entity;
+ return Wtm.CallAPI("mainhost", $"/api/_frameworkrole/{Id}").GetAwaiter().GetResult().Data.Entity;
}
else
{
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkRoleVMs/FrameworkRoleVM.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkRoleVMs/FrameworkRoleVM.cs
index 8066549fb..64b22fff4 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkRoleVMs/FrameworkRoleVM.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkRoleVMs/FrameworkRoleVM.cs
@@ -21,13 +21,13 @@ public override DuplicatedInfo SetDuplicatedCheck()
public override void DoAdd()
{
base.DoAdd();
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override void DoEdit(bool updateAllFields = false)
{
base.DoEdit(updateAllFields);
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override async Task DoDeleteAsync()
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkTenantVMs/FrameworkTenantVM.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkTenantVMs/FrameworkTenantVM.cs
index 3b3ca2681..4620f5433 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkTenantVMs/FrameworkTenantVM.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo.ViewModel/FrameworkTenantVMs/FrameworkTenantVM.cs
@@ -79,7 +79,7 @@ private void TenantOperation()
if (tenantdc.Database.EnsureCreated() == true)
{
tenantdc.SetTenantCode(Entity.TCode);
- tenantdc.DataInit(Wtm.GlobaInfo.AllModule, Wtm.GlobaInfo.IsSpa).Wait();
+ tenantdc.DataInit(Wtm.GlobaInfo.AllModule, Wtm.GlobaInfo.IsSpa).GetAwaiter().GetResult();
}
AddTenantData(tenantdc, fps);
}
@@ -127,7 +127,7 @@ private void AddTenantData(IDataContext dc, List fps)
}
dc.SaveChanges();
var key = $"{GlobalConstants.CacheKey.UserInfo}:{"admin" + "$`$" + Entity.TCode}";
- Cache.DeleteAsync(key).Wait();
+ Cache.DeleteAsync(key).GetAwaiter().GetResult();
}
public override void DoDelete()
{
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/AccountController.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/AccountController.cs
index 09ff16eef..5cb507abe 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/AccountController.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/AccountController.cs
@@ -137,9 +137,9 @@ public IActionResult Reg(SimpleReg regInfo)
[HttpPost("[action]")]
[AllRights]
[ProducesResponseType(typeof(Token), StatusCodes.Status200OK)]
- public IActionResult RefreshToken(string refreshToken)
+ public async Task RefreshToken(string refreshToken)
{
- var rv = Wtm.RefreshToken();
+ var rv = await Wtm.RefreshTokenAsync();
if (rv == null)
{
return BadRequest();
@@ -198,11 +198,11 @@ public IActionResult CheckUserInfo(bool IsApi = true)
[AllRights]
[HttpPost("[action]")]
- public IActionResult ChangePassword(ChangePasswordVM vm)
+ public async Task ChangePassword(ChangePasswordVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (!ModelState.IsValid)
{
@@ -243,11 +243,11 @@ public async Task Logout()
[HttpGet("GetFrameworkRoles")]
[ActionDescription("GetRoles")]
[AllRights]
- public IActionResult GetFrameworkRoles()
+ public async Task GetFrameworkRoles()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkRoles").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkRoles");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.RoleName, x => x.RoleCode));
}
@@ -255,11 +255,11 @@ public IActionResult GetFrameworkRoles()
[HttpGet("GetFrameworkGroups")]
[ActionDescription("GetGroups")]
[AllRights]
- public IActionResult GetFrameworkGroups()
+ public async Task GetFrameworkGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -267,11 +267,11 @@ public IActionResult GetFrameworkGroups()
[HttpGet("GetFrameworkGroupsTree")]
[ActionDescription("GetGroupsTree")]
[AllRights]
- public IActionResult GetFrameworkGroupsTree()
+ public async Task GetFrameworkGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -279,11 +279,11 @@ public IActionResult GetFrameworkGroupsTree()
[HttpGet("GetUserById")]
[AllRights]
- public IActionResult GetUserById(string keywords)
+ public async Task GetUserById(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserById").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserById");
}
var users = DC.Set().Where(x => x.ITCode.ToLower().StartsWith(keywords.ToLower())).GetSelectListItems(Wtm, x => x.Name + "(" + x.ITCode + ")", x => x.ITCode);
return Ok(users);
@@ -291,11 +291,11 @@ public IActionResult GetUserById(string keywords)
[HttpGet("GetUserByGroup")]
[AllRights]
- public IActionResult GetUserByGroup(string keywords)
+ public async Task GetUserByGroup(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserByGroup").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserByGroup");
}
var users = DC.Set().Where(x => x.GroupCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
@@ -303,11 +303,11 @@ public IActionResult GetUserByGroup(string keywords)
[HttpGet("GetUserByRole")]
[AllRights]
- public IActionResult GetUserByRole(string keywords)
+ public async Task GetUserByRole(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserByRole").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserByRole");
}
var users = DC.Set().Where(x => x.RoleCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/DataPrivilegeController.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/DataPrivilegeController.cs
index 0521d7d46..63b3187d1 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/DataPrivilegeController.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/DataPrivilegeController.cs
@@ -137,22 +137,22 @@ public ActionResult GetPrivileges()
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetUserGroups()
+ public async Task GetUserGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetUserGroupsTree()
+ public async Task GetUserGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkGroupController.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkGroupController.cs
index 607479b1e..ba8cb3f6f 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkGroupController.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkGroupController.cs
@@ -19,11 +19,11 @@ public class FrameworkGroupController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkGroupSearcher searcher)
+ public async Task Search(FrameworkGroupSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -128,7 +128,7 @@ public async Task BatchDelete(string[] ids)
DC.Set().RemoveRange(gr);
DC.SaveChanges();
await Wtm.RemoveUserCacheByGroup(GroupCode.ToArray());
- Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(ids.Count());
}
}
@@ -185,7 +185,7 @@ public IActionResult GetExcelTemplate()
[ActionDescription("Sys.Import")]
[HttpPost("[action]")]
- public ActionResult Import(FrameworkGroupImportVM vm)
+ public async Task Import(FrameworkGroupImportVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
@@ -198,18 +198,18 @@ public ActionResult Import(FrameworkGroupImportVM vm)
}
else
{
- Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(vm.EntityList.Count);
}
}
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetParents()
+ public async Task GetParents()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParents").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParents");
}
var data = DC.Set().GetSelectListItems(Wtm, x => x.GroupName);
return Ok(data);
@@ -217,11 +217,11 @@ public IActionResult GetParents()
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetParentsTree()
+ public async Task GetParentsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParentsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParentsTree");
}
var data = DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName);
return Ok(data);
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkRoleController.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkRoleController.cs
index 62724cfde..ef7ce2a10 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkRoleController.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkRoleController.cs
@@ -19,11 +19,11 @@ public class FrameworkRoleController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkRoleSearcher searcher)
+ public async Task Search(FrameworkRoleSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -216,7 +216,7 @@ public IActionResult GetExcelTemplate()
[ActionDescription("Sys.Import")]
[HttpPost("[action]")]
- public ActionResult Import(FrameworkRoleImportVM vm)
+ public async Task Import(FrameworkRoleImportVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
@@ -229,7 +229,7 @@ public ActionResult Import(FrameworkRoleImportVM vm)
}
else
{
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(vm.EntityList.Count);
}
}
diff --git a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkUserController.cs b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkUserController.cs
index e213fe8dd..0b9ab286c 100644
--- a/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkUserController.cs
+++ b/demo/WalkingTec.Mvvm.BlazorDemo/WalkingTec.Mvvm.BlazorDemo/_Admin/Controllers/FrameworkUserController.cs
@@ -20,11 +20,11 @@ public class FrameworkUserController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkUserSearcher searcher)
+ public async Task Search(FrameworkUserSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -222,11 +222,11 @@ public ActionResult Import(FrameworkUserImportVM vm)
[HttpGet("GetFrameworkRoles")]
[ActionDescription("GetRoles")]
[AllRights]
- public IActionResult GetFrameworkRoles()
+ public async Task GetFrameworkRoles()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkRoles").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkRoles");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.RoleName, x => x.RoleCode));
}
@@ -234,11 +234,11 @@ public IActionResult GetFrameworkRoles()
[HttpGet("GetFrameworkGroups")]
[ActionDescription("GetGroups")]
[AllRights]
- public IActionResult GetFrameworkGroups()
+ public async Task GetFrameworkGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -246,11 +246,11 @@ public IActionResult GetFrameworkGroups()
[HttpGet("GetFrameworkGroupsTree")]
[ActionDescription("GetGroupsTree")]
[AllRights]
- public IActionResult GetFrameworkGroupsTree()
+ public async Task GetFrameworkGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -258,11 +258,11 @@ public IActionResult GetFrameworkGroupsTree()
[HttpGet("GetUserById")]
[AllRights]
- public IActionResult GetUserById(string keywords)
+ public async Task GetUserById(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserById").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserById");
}
var users = DC.Set().Where(x => x.ITCode.ToLower().StartsWith(keywords.ToLower())).GetSelectListItems(Wtm, x => x.Name + "(" + x.ITCode + ")", x => x.ITCode);
return Ok(users);
@@ -270,11 +270,11 @@ public IActionResult GetUserById(string keywords)
[HttpGet("GetUserByGroup")]
[AllRights]
- public IActionResult GetUserByGroup(string keywords)
+ public async Task GetUserByGroup(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByGroup").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByGroup");
}
var users = DC.Set().Where(x => x.GroupCode == keywords).Select(x=>x.UserCode).ToList();
return Ok(users);
@@ -282,11 +282,11 @@ public IActionResult GetUserByGroup(string keywords)
[HttpGet("GetUserByRole")]
[AllRights]
- public IActionResult GetUserByRole(string keywords)
+ public async Task GetUserByRole(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByRole").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByRole");
}
var users = DC.Set().Where(x => x.RoleCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/AccountController.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/AccountController.cs
index c693ede36..d94610491 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/AccountController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/AccountController.cs
@@ -137,9 +137,9 @@ public IActionResult Reg(SimpleReg regInfo)
[HttpPost("[action]")]
[AllRights]
[ProducesResponseType(typeof(Token), StatusCodes.Status200OK)]
- public IActionResult RefreshToken(string refreshToken)
+ public async Task RefreshToken(string refreshToken)
{
- var rv = Wtm.RefreshToken();
+ var rv = await Wtm.RefreshTokenAsync();
if (rv == null)
{
return BadRequest();
@@ -198,11 +198,11 @@ public IActionResult CheckUserInfo(bool IsApi = true)
[AllRights]
[HttpPost("[action]")]
- public IActionResult ChangePassword(ChangePasswordVM vm)
+ public async Task ChangePassword(ChangePasswordVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (!ModelState.IsValid)
{
@@ -243,11 +243,11 @@ public async Task Logout()
[HttpGet("GetFrameworkRoles")]
[ActionDescription("GetRoles")]
[AllRights]
- public IActionResult GetFrameworkRoles()
+ public async Task GetFrameworkRoles()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkRoles").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkRoles");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.RoleName, x => x.RoleCode));
}
@@ -255,11 +255,11 @@ public IActionResult GetFrameworkRoles()
[HttpGet("GetFrameworkGroups")]
[ActionDescription("GetGroups")]
[AllRights]
- public IActionResult GetFrameworkGroups()
+ public async Task GetFrameworkGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -267,11 +267,11 @@ public IActionResult GetFrameworkGroups()
[HttpGet("GetFrameworkGroupsTree")]
[ActionDescription("GetGroupsTree")]
[AllRights]
- public IActionResult GetFrameworkGroupsTree()
+ public async Task GetFrameworkGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -279,11 +279,11 @@ public IActionResult GetFrameworkGroupsTree()
[HttpGet("GetUserById")]
[AllRights]
- public IActionResult GetUserById(string keywords)
+ public async Task GetUserById(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserById").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserById");
}
var users = DC.Set().Where(x => x.ITCode.ToLower().StartsWith(keywords.ToLower())).GetSelectListItems(Wtm, x => x.Name + "(" + x.ITCode + ")", x => x.ITCode);
return Ok(users);
@@ -291,11 +291,11 @@ public IActionResult GetUserById(string keywords)
[HttpGet("GetUserByGroup")]
[AllRights]
- public IActionResult GetUserByGroup(string keywords)
+ public async Task GetUserByGroup(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserByGroup").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserByGroup");
}
var users = DC.Set().Where(x => x.GroupCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
@@ -303,11 +303,11 @@ public IActionResult GetUserByGroup(string keywords)
[HttpGet("GetUserByRole")]
[AllRights]
- public IActionResult GetUserByRole(string keywords)
+ public async Task GetUserByRole(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserByRole").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserByRole");
}
var users = DC.Set().Where(x => x.RoleCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/DataPrivilegeController.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/DataPrivilegeController.cs
index 0521d7d46..63b3187d1 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/DataPrivilegeController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/DataPrivilegeController.cs
@@ -137,22 +137,22 @@ public ActionResult GetPrivileges()
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetUserGroups()
+ public async Task GetUserGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetUserGroupsTree()
+ public async Task GetUserGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkGroupController.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkGroupController.cs
index 607479b1e..ba8cb3f6f 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkGroupController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkGroupController.cs
@@ -19,11 +19,11 @@ public class FrameworkGroupController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkGroupSearcher searcher)
+ public async Task Search(FrameworkGroupSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -128,7 +128,7 @@ public async Task BatchDelete(string[] ids)
DC.Set().RemoveRange(gr);
DC.SaveChanges();
await Wtm.RemoveUserCacheByGroup(GroupCode.ToArray());
- Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(ids.Count());
}
}
@@ -185,7 +185,7 @@ public IActionResult GetExcelTemplate()
[ActionDescription("Sys.Import")]
[HttpPost("[action]")]
- public ActionResult Import(FrameworkGroupImportVM vm)
+ public async Task Import(FrameworkGroupImportVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
@@ -198,18 +198,18 @@ public ActionResult Import(FrameworkGroupImportVM vm)
}
else
{
- Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(vm.EntityList.Count);
}
}
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetParents()
+ public async Task GetParents()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParents").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParents");
}
var data = DC.Set().GetSelectListItems(Wtm, x => x.GroupName);
return Ok(data);
@@ -217,11 +217,11 @@ public IActionResult GetParents()
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetParentsTree()
+ public async Task GetParentsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParentsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParentsTree");
}
var data = DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName);
return Ok(data);
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkRoleController.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkRoleController.cs
index 62724cfde..ef7ce2a10 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkRoleController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkRoleController.cs
@@ -19,11 +19,11 @@ public class FrameworkRoleController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkRoleSearcher searcher)
+ public async Task Search(FrameworkRoleSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -216,7 +216,7 @@ public IActionResult GetExcelTemplate()
[ActionDescription("Sys.Import")]
[HttpPost("[action]")]
- public ActionResult Import(FrameworkRoleImportVM vm)
+ public async Task Import(FrameworkRoleImportVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
@@ -229,7 +229,7 @@ public ActionResult Import(FrameworkRoleImportVM vm)
}
else
{
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(vm.EntityList.Count);
}
}
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkUserController.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkUserController.cs
index e213fe8dd..0b9ab286c 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkUserController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ApiControllers/FrameworkUserController.cs
@@ -20,11 +20,11 @@ public class FrameworkUserController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkUserSearcher searcher)
+ public async Task Search(FrameworkUserSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -222,11 +222,11 @@ public ActionResult Import(FrameworkUserImportVM vm)
[HttpGet("GetFrameworkRoles")]
[ActionDescription("GetRoles")]
[AllRights]
- public IActionResult GetFrameworkRoles()
+ public async Task GetFrameworkRoles()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkRoles").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkRoles");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.RoleName, x => x.RoleCode));
}
@@ -234,11 +234,11 @@ public IActionResult GetFrameworkRoles()
[HttpGet("GetFrameworkGroups")]
[ActionDescription("GetGroups")]
[AllRights]
- public IActionResult GetFrameworkGroups()
+ public async Task GetFrameworkGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -246,11 +246,11 @@ public IActionResult GetFrameworkGroups()
[HttpGet("GetFrameworkGroupsTree")]
[ActionDescription("GetGroupsTree")]
[AllRights]
- public IActionResult GetFrameworkGroupsTree()
+ public async Task GetFrameworkGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -258,11 +258,11 @@ public IActionResult GetFrameworkGroupsTree()
[HttpGet("GetUserById")]
[AllRights]
- public IActionResult GetUserById(string keywords)
+ public async Task GetUserById(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserById").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserById");
}
var users = DC.Set().Where(x => x.ITCode.ToLower().StartsWith(keywords.ToLower())).GetSelectListItems(Wtm, x => x.Name + "(" + x.ITCode + ")", x => x.ITCode);
return Ok(users);
@@ -270,11 +270,11 @@ public IActionResult GetUserById(string keywords)
[HttpGet("GetUserByGroup")]
[AllRights]
- public IActionResult GetUserByGroup(string keywords)
+ public async Task GetUserByGroup(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByGroup").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByGroup");
}
var users = DC.Set().Where(x => x.GroupCode == keywords).Select(x=>x.UserCode).ToList();
return Ok(users);
@@ -282,11 +282,11 @@ public IActionResult GetUserByGroup(string keywords)
[HttpGet("GetUserByRole")]
[AllRights]
- public IActionResult GetUserByRole(string keywords)
+ public async Task GetUserByRole(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByRole").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByRole");
}
var users = DC.Set().Where(x => x.RoleCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/DataPrivilegeController.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/DataPrivilegeController.cs
index d8bf17704..4d4e6dadb 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/DataPrivilegeController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/DataPrivilegeController.cs
@@ -133,11 +133,11 @@ public IActionResult ExportExcel(DataPrivilegeListVM vm)
return vm.GetExportData();
}
[AllRights]
- public IActionResult GetUserGroups()
+ public async Task GetUserGroups()
{
WalkingTec.Mvvm.Admin.Api.DataPrivilegeController userapi = new Mvvm.Admin.Api.DataPrivilegeController();
userapi.Wtm = Wtm;
- var rv = userapi.GetUserGroupsTree() as OkObjectResult;
+ var rv = (await userapi.GetUserGroupsTree()) as OkObjectResult;
List users = new List();
if (rv != null && rv.Value is string && rv.Value != null)
{
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkGroupController.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkGroupController.cs
index e0f76adea..f07770f19 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkGroupController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkGroupController.cs
@@ -26,12 +26,12 @@ public ActionResult Index()
[ActionDescription("Sys.Search")]
[HttpPost]
- public IActionResult Search(FrameworkGroupSearcher searcher)
+ public async Task Search(FrameworkGroupSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
searcher.IsPlainText = false;
- return Wtm.CallAPI("mainhost", "/api/_frameworkgroup/search", HttpMethodEnum.POST, searcher).Result.ToActionResult();
+ return (await Wtm.CallAPI("mainhost", "/api/_frameworkgroup/search", HttpMethodEnum.POST, searcher)).ToActionResult();
}
var vm = Wtm.CreateVM(passInit: true);
if (ModelState.IsValid)
@@ -188,7 +188,7 @@ public ActionResult Import()
[HttpPost]
[ActionDescription("Sys.Import")]
- public ActionResult Import(FrameworkGroupImportVM vm, IFormCollection nouse)
+ public async Task Import(FrameworkGroupImportVM vm, IFormCollection nouse)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
@@ -200,7 +200,7 @@ public ActionResult Import(FrameworkGroupImportVM vm, IFormCollection nouse)
}
else
{
- Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant);
return FFResult().CloseDialog().RefreshGrid().Alert(Localizer["Sys.ImportSuccess", vm.EntityList.Count.ToString()]);
}
}
@@ -232,11 +232,11 @@ public IActionResult ExportExcel(FrameworkGroupListVM vm)
}
[AllRights]
- public IActionResult GetParents()
+ public async Task GetParents()
{
WalkingTec.Mvvm.Admin.Api.FrameworkGroupController userapi = new Mvvm.Admin.Api.FrameworkGroupController();
userapi.Wtm = Wtm;
- var rv = userapi.GetParentsTree() as OkObjectResult;
+ var rv = (await userapi.GetParentsTree()) as OkObjectResult;
List users = new List();
if (rv != null && rv.Value is string && rv.Value != null)
{
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkRoleController.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkRoleController.cs
index c15e1f29d..d8b089bd0 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkRoleController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkRoleController.cs
@@ -23,12 +23,12 @@ public ActionResult Index()
}
[ActionDescription("Sys.Search")]
[HttpPost]
- public IActionResult Search(FrameworkRoleSearcher searcher)
+ public async Task Search(FrameworkRoleSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
searcher.IsPlainText = false;
- return Wtm.CallAPI("mainhost", "/api/_frameworkrole/search", HttpMethodEnum.POST, searcher).Result.ToActionResult();
+ return (await Wtm.CallAPI("mainhost", "/api/_frameworkrole/search", HttpMethodEnum.POST, searcher)).ToActionResult();
}
var vm = Wtm.CreateVM(passInit: true);
if (ModelState.IsValid)
@@ -184,7 +184,7 @@ public ActionResult Import()
[HttpPost]
[ActionDescription("Sys.Import")]
- public ActionResult Import(FrameworkRoleImportVM vm, IFormCollection nouse)
+ public async Task Import(FrameworkRoleImportVM vm, IFormCollection nouse)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
@@ -196,7 +196,7 @@ public ActionResult Import(FrameworkRoleImportVM vm, IFormCollection nouse)
}
else
{
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant);
return FFResult().CloseDialog().RefreshGrid().Alert(Localizer["Sys.ImportSuccess", vm.EntityList.Count.ToString()]);
}
}
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkUserController.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkUserController.cs
index 8c9b81c8a..86ba42405 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkUserController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/Controllers/FrameworkUserController.cs
@@ -372,11 +372,11 @@ public ActionResult Enable(Guid id, bool enable)
}
[AllRights]
- public ActionResult GetUserById(string keywords)
+ public async Task GetUserById(string keywords)
{
WalkingTec.Mvvm.Admin.Api.AccountController userapi = new WalkingTec.Mvvm.Admin.Api.AccountController();
userapi.Wtm = Wtm;
- var rv = userapi.GetUserById(keywords) as OkObjectResult;
+ var rv = (await userapi.GetUserById(keywords)) as OkObjectResult;
List users = new List();
if (rv != null && rv.Value is string && rv.Value != null)
{
@@ -402,11 +402,11 @@ public IActionResult ExportExcel(FrameworkUserListVM vm)
}
[AllRights]
- public IActionResult GetFrameworkRoles()
+ public async Task GetFrameworkRoles()
{
WalkingTec.Mvvm.Admin.Api.AccountController userapi = new WalkingTec.Mvvm.Admin.Api.AccountController();
userapi.Wtm = Wtm;
- var rv = userapi.GetFrameworkRoles() as OkObjectResult;
+ var rv = (await userapi.GetFrameworkRoles()) as OkObjectResult;
List users = new List();
if (rv != null && rv.Value is string && rv.Value != null)
{
@@ -420,11 +420,11 @@ public IActionResult GetFrameworkRoles()
}
[AllRights]
- public IActionResult GetFrameworkGroups()
+ public async Task GetFrameworkGroups()
{
WalkingTec.Mvvm.Admin.Api.AccountController userapi = new WalkingTec.Mvvm.Admin.Api.AccountController();
userapi.Wtm = Wtm;
- var rv = userapi.GetFrameworkGroupsTree() as OkObjectResult;
+ var rv = (await userapi.GetFrameworkGroupsTree()) as OkObjectResult;
List users = new List();
if (rv != null && rv.Value is string && rv.Value != null)
{
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeListVM.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeListVM.cs
index 6b9464eac..8af432d81 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeListVM.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeListVM.cs
@@ -130,7 +130,7 @@ public override void AfterDoSearcher()
Dictionary groupdata = new Dictionary();
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- var dd = Wtm.CallAPI>("mainhost", "/api/_account/GetFrameworkGroups").Result;
+ var dd = Wtm.CallAPI>("mainhost", "/api/_account/GetFrameworkGroups").GetAwaiter().GetResult();
if(dd.Data != null)
{
foreach (var item in dd.Data)
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeVM.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeVM.cs
index aa3564868..e7ecde6ef 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeVM.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeVM.cs
@@ -77,7 +77,7 @@ public override void Validate()
string user = null;
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- var check = Wtm.CallAPI>("mainhost", "/api/_account/GetUserById").Result;
+ var check = Wtm.CallAPI>("mainhost", "/api/_account/GetUserById").GetAwaiter().GetResult();
if (check.Data != null)
{
user = check.Data.Where(x => x.Value.ToString() == Entity.UserCode).Select(x => x.Value.ToString()).FirstOrDefault();
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupMDVM.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupMDVM.cs
index 0a1452829..a78dba9b4 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupMDVM.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupMDVM.cs
@@ -87,7 +87,7 @@ public bool DoChange()
}
}
DC.SaveChanges();
- Wtm.RemoveUserCacheByGroup(GroupCode).Wait();
+ Wtm.RemoveUserCacheByGroup(GroupCode).GetAwaiter().GetResult();
return true;
}
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupVM.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupVM.cs
index 30326329f..0a7a93357 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupVM.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupVM.cs
@@ -34,13 +34,13 @@ public override void Validate()
public override void DoAdd()
{
base.DoAdd();
- Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override void DoEdit(bool updateAllFields = false)
{
base.DoEdit(updateAllFields);
- Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override async Task DoDeleteAsync()
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM.cs
index f39579737..4dec56423 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM.cs
@@ -392,7 +392,7 @@ public void AddPrivilege(List menuids)
}
}
DC.SaveChanges();
- Wtm.RemoveUserCacheByRole(SelectedRolesIds.ToArray()).Wait();
+ Wtm.RemoveUserCacheByRole(SelectedRolesIds.ToArray()).GetAwaiter().GetResult();
}
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM2.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM2.cs
index 3550ccff2..9602caa94 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM2.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM2.cs
@@ -269,7 +269,7 @@ public void AddPrivilege(List menuids)
}
}
DC.SaveChanges();
- Wtm.RemoveUserCacheByRole(SelectedRolesCodes.ToArray()).Wait();
+ Wtm.RemoveUserCacheByRole(SelectedRolesCodes.ToArray()).GetAwaiter().GetResult();
}
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM.cs
index 44b668fc6..228668607 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM.cs
@@ -21,7 +21,7 @@ protected override FrameworkRole GetById(object Id)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Wtm.CallAPI("mainhost", $"/api/_frameworkrole/{Id}").Result.Data.Entity;
+ return Wtm.CallAPI("mainhost", $"/api/_frameworkrole/{Id}").GetAwaiter().GetResult().Data.Entity;
}
else
{
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM2.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM2.cs
index fa81f98cd..f897b0b83 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM2.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM2.cs
@@ -24,7 +24,7 @@ protected override FrameworkRole GetById(object Id)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Wtm.CallAPI("mainhost", $"/api/_frameworkrole/{Id}").Result.Data.Entity;
+ return Wtm.CallAPI("mainhost", $"/api/_frameworkrole/{Id}").GetAwaiter().GetResult().Data.Entity;
}
else
{
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleVM.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleVM.cs
index 8066549fb..64b22fff4 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleVM.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleVM.cs
@@ -21,13 +21,13 @@ public override DuplicatedInfo SetDuplicatedCheck()
public override void DoAdd()
{
base.DoAdd();
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override void DoEdit(bool updateAllFields = false)
{
base.DoEdit(updateAllFields);
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override async Task DoDeleteAsync()
diff --git a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkTenantVMs/FrameworkTenantVM.cs b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkTenantVMs/FrameworkTenantVM.cs
index 3b3ca2681..4620f5433 100644
--- a/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkTenantVMs/FrameworkTenantVM.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Areas/_Admin/ViewModels/FrameworkTenantVMs/FrameworkTenantVM.cs
@@ -79,7 +79,7 @@ private void TenantOperation()
if (tenantdc.Database.EnsureCreated() == true)
{
tenantdc.SetTenantCode(Entity.TCode);
- tenantdc.DataInit(Wtm.GlobaInfo.AllModule, Wtm.GlobaInfo.IsSpa).Wait();
+ tenantdc.DataInit(Wtm.GlobaInfo.AllModule, Wtm.GlobaInfo.IsSpa).GetAwaiter().GetResult();
}
AddTenantData(tenantdc, fps);
}
@@ -127,7 +127,7 @@ private void AddTenantData(IDataContext dc, List fps)
}
dc.SaveChanges();
var key = $"{GlobalConstants.CacheKey.UserInfo}:{"admin" + "$`$" + Entity.TCode}";
- Cache.DeleteAsync(key).Wait();
+ Cache.DeleteAsync(key).GetAwaiter().GetResult();
}
public override void DoDelete()
{
diff --git a/demo/WalkingTec.Mvvm.Demo/Controllers/HomeController.cs b/demo/WalkingTec.Mvvm.Demo/Controllers/HomeController.cs
index 6f4c7d197..4b2275bfa 100644
--- a/demo/WalkingTec.Mvvm.Demo/Controllers/HomeController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Controllers/HomeController.cs
@@ -162,7 +162,7 @@ public Github GetGithubInfo()
{
var rv = Wtm.ReadFromCache("githubinfo", () =>
{
- var s = Wtm.CallAPI("github", "repos/dotnetcore/wtm", 60).Result;
+ var s = Wtm.CallAPI("github", "repos/dotnetcore/wtm", 60).GetAwaiter().GetResult();
return s.Data;
}, 1800);
diff --git a/demo/WalkingTec.Mvvm.Demo/Controllers/LoginController.cs b/demo/WalkingTec.Mvvm.Demo/Controllers/LoginController.cs
index 47a7eaaba..20d31c13f 100644
--- a/demo/WalkingTec.Mvvm.Demo/Controllers/LoginController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Controllers/LoginController.cs
@@ -129,7 +129,7 @@ public async Task Logout()
}
else
{
- Wtm.CallAPI("mainhost", "/api/_account/logout", HttpMethodEnum.GET, new { }, 10).Wait();
+ await Wtm.CallAPI("mainhost", "/api/_account/logout", HttpMethodEnum.GET, new { }, 10);
HttpContext.Response.Redirect(ConfigInfo.MainHost);
}
}
@@ -146,11 +146,11 @@ public ActionResult ChangePassword()
[AllRights]
[HttpPost]
[ActionDescription("ChangePassword")]
- public ActionResult ChangePassword(ChangePasswordVM vm)
+ public async Task ChangePassword(ChangePasswordVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- var result = Wtm.CallAPI("mainhost", "/api/_account/ChangePassword", HttpMethodEnum.POST, vm, 10).Result;
+ var result = await Wtm.CallAPI("mainhost", "/api/_account/ChangePassword", HttpMethodEnum.POST, vm, 10);
if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
return FFResult().CloseDialog().Alert(Localizer["Login.ChangePasswordSuccess"]);
diff --git a/demo/WalkingTec.Mvvm.Demo/Controllers/SchoolController.cs b/demo/WalkingTec.Mvvm.Demo/Controllers/SchoolController.cs
index 9a2d8c5a2..bdf14d4c2 100644
--- a/demo/WalkingTec.Mvvm.Demo/Controllers/SchoolController.cs
+++ b/demo/WalkingTec.Mvvm.Demo/Controllers/SchoolController.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NPOI.HSSF.Util;
@@ -83,7 +84,7 @@ public ActionResult Create()
[HttpPost]
[ActionDescription("新建")]
- public ActionResult Create(SchoolVM vm)
+ public async Task Create(SchoolVM vm)
{
if (!ModelState.IsValid)
{
@@ -92,7 +93,7 @@ public ActionResult Create(SchoolVM vm)
else
{
vm.DoAdd();
- var rv = vm.StartWorkflowAsync("学校审批").Result;
+ var rv = await vm.StartWorkflowAsync("学校审批");
if (!ModelState.IsValid)
{
vm.DoReInit();
@@ -116,7 +117,7 @@ public ActionResult Edit(string id)
[ActionDescription("修改")]
[HttpPost]
- public ActionResult Edit(SchoolVM vm)
+ public async Task Edit(SchoolVM vm)
{
if (!ModelState.IsValid)
{
@@ -125,7 +126,7 @@ public ActionResult Edit(SchoolVM vm)
else
{
vm.DoEdit();
- _ = vm.ContinueWorkflowAsync("同意", "adf adf asdf ","学校审批").Result;
+ _ = await vm.ContinueWorkflowAsync("同意", "adf adf asdf ","学校审批");
if (!ModelState.IsValid)
{
vm.DoReInit();
@@ -166,10 +167,10 @@ public ActionResult Delete(int id, IFormCollection nouse)
#region 详细
[ActionDescription("详细")]
- public ActionResult Details(int id)
+ public async Task Details(int id)
{
var vm = Wtm.CreateVM(id);
- var test =vm.GetWorkflowTimeLineAsync().Result;
+ var test = await vm.GetWorkflowTimeLineAsync();
return PartialView(vm);
}
#endregion
diff --git a/demo/WalkingTec.Mvvm.Demo/ViewModels/HomeVMs/RegVM.cs b/demo/WalkingTec.Mvvm.Demo/ViewModels/HomeVMs/RegVM.cs
index 5b8cfa837..1e7d99c2c 100644
--- a/demo/WalkingTec.Mvvm.Demo/ViewModels/HomeVMs/RegVM.cs
+++ b/demo/WalkingTec.Mvvm.Demo/ViewModels/HomeVMs/RegVM.cs
@@ -72,7 +72,7 @@ public bool DoReg()
DC.Set().Add(user);
DC.SaveChanges();
var vm = Wtm.CreateVM(user.ID);
- _=vm.StartWorkflowAsync().Result;
+ _=vm.StartWorkflowAsync().GetAwaiter().GetResult();
return true;
}
}
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/AccountController.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/AccountController.cs
index 81dce9a3e..4f477c945 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/AccountController.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/AccountController.cs
@@ -137,9 +137,9 @@ public IActionResult Reg(SimpleReg regInfo)
[HttpPost("[action]")]
[AllRights]
[ProducesResponseType(typeof(Token), StatusCodes.Status200OK)]
- public IActionResult RefreshToken(string refreshToken)
+ public async Task RefreshToken(string refreshToken)
{
- var rv = Wtm.RefreshToken();
+ var rv = await Wtm.RefreshTokenAsync();
if (rv == null)
{
return BadRequest();
@@ -190,11 +190,11 @@ public IActionResult CheckUserInfo(bool IsApi = true)
[AllRights]
[HttpPost("[action]")]
- public IActionResult ChangePassword(ChangePasswordVM vm)
+ public async Task ChangePassword(ChangePasswordVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (!ModelState.IsValid)
{
@@ -235,11 +235,11 @@ public async Task Logout()
[HttpGet("GetFrameworkRoles")]
[ActionDescription("GetRoles")]
[AllRights]
- public IActionResult GetFrameworkRoles()
+ public async Task GetFrameworkRoles()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkRoles").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkRoles");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.RoleName, x => x.RoleCode));
}
@@ -247,11 +247,11 @@ public IActionResult GetFrameworkRoles()
[HttpGet("GetFrameworkGroups")]
[ActionDescription("GetGroups")]
[AllRights]
- public IActionResult GetFrameworkGroups()
+ public async Task GetFrameworkGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -259,11 +259,11 @@ public IActionResult GetFrameworkGroups()
[HttpGet("GetFrameworkGroupsTree")]
[ActionDescription("GetGroupsTree")]
[AllRights]
- public IActionResult GetFrameworkGroupsTree()
+ public async Task GetFrameworkGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -271,11 +271,11 @@ public IActionResult GetFrameworkGroupsTree()
[HttpGet("GetUserById")]
[AllRights]
- public IActionResult GetUserById(string keywords)
+ public async Task GetUserById(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserById").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserById");
}
var users = DC.Set().Where(x => x.ITCode.ToLower().StartsWith(keywords.ToLower())).GetSelectListItems(Wtm, x => x.Name + "(" + x.ITCode + ")", x => x.ITCode);
return Ok(users);
@@ -283,11 +283,11 @@ public IActionResult GetUserById(string keywords)
[HttpGet("GetUserByGroup")]
[AllRights]
- public IActionResult GetUserByGroup(string keywords)
+ public async Task GetUserByGroup(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserByGroup").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserByGroup");
}
var users = DC.Set().Where(x => x.GroupCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
@@ -295,11 +295,11 @@ public IActionResult GetUserByGroup(string keywords)
[HttpGet("GetUserByRole")]
[AllRights]
- public IActionResult GetUserByRole(string keywords)
+ public async Task GetUserByRole(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserByRole").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserByRole");
}
var users = DC.Set().Where(x => x.RoleCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/DataPrivilegeController.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/DataPrivilegeController.cs
index 0521d7d46..63b3187d1 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/DataPrivilegeController.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/DataPrivilegeController.cs
@@ -137,22 +137,22 @@ public ActionResult GetPrivileges()
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetUserGroups()
+ public async Task GetUserGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetUserGroupsTree()
+ public async Task GetUserGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkGroupController.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkGroupController.cs
index 607479b1e..ba8cb3f6f 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkGroupController.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkGroupController.cs
@@ -19,11 +19,11 @@ public class FrameworkGroupController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkGroupSearcher searcher)
+ public async Task Search(FrameworkGroupSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -128,7 +128,7 @@ public async Task BatchDelete(string[] ids)
DC.Set().RemoveRange(gr);
DC.SaveChanges();
await Wtm.RemoveUserCacheByGroup(GroupCode.ToArray());
- Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(ids.Count());
}
}
@@ -185,7 +185,7 @@ public IActionResult GetExcelTemplate()
[ActionDescription("Sys.Import")]
[HttpPost("[action]")]
- public ActionResult Import(FrameworkGroupImportVM vm)
+ public async Task Import(FrameworkGroupImportVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
@@ -198,18 +198,18 @@ public ActionResult Import(FrameworkGroupImportVM vm)
}
else
{
- Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(vm.EntityList.Count);
}
}
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetParents()
+ public async Task GetParents()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParents").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParents");
}
var data = DC.Set().GetSelectListItems(Wtm, x => x.GroupName);
return Ok(data);
@@ -217,11 +217,11 @@ public IActionResult GetParents()
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetParentsTree()
+ public async Task GetParentsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParentsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParentsTree");
}
var data = DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName);
return Ok(data);
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkRoleController.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkRoleController.cs
index 62724cfde..ef7ce2a10 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkRoleController.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkRoleController.cs
@@ -19,11 +19,11 @@ public class FrameworkRoleController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkRoleSearcher searcher)
+ public async Task Search(FrameworkRoleSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -216,7 +216,7 @@ public IActionResult GetExcelTemplate()
[ActionDescription("Sys.Import")]
[HttpPost("[action]")]
- public ActionResult Import(FrameworkRoleImportVM vm)
+ public async Task Import(FrameworkRoleImportVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
@@ -229,7 +229,7 @@ public ActionResult Import(FrameworkRoleImportVM vm)
}
else
{
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(vm.EntityList.Count);
}
}
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkUserController.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkUserController.cs
index e213fe8dd..0b9ab286c 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkUserController.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/Controllers/FrameworkUserController.cs
@@ -20,11 +20,11 @@ public class FrameworkUserController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkUserSearcher searcher)
+ public async Task Search(FrameworkUserSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -222,11 +222,11 @@ public ActionResult Import(FrameworkUserImportVM vm)
[HttpGet("GetFrameworkRoles")]
[ActionDescription("GetRoles")]
[AllRights]
- public IActionResult GetFrameworkRoles()
+ public async Task GetFrameworkRoles()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkRoles").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkRoles");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.RoleName, x => x.RoleCode));
}
@@ -234,11 +234,11 @@ public IActionResult GetFrameworkRoles()
[HttpGet("GetFrameworkGroups")]
[ActionDescription("GetGroups")]
[AllRights]
- public IActionResult GetFrameworkGroups()
+ public async Task GetFrameworkGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -246,11 +246,11 @@ public IActionResult GetFrameworkGroups()
[HttpGet("GetFrameworkGroupsTree")]
[ActionDescription("GetGroupsTree")]
[AllRights]
- public IActionResult GetFrameworkGroupsTree()
+ public async Task GetFrameworkGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetFrameworkGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -258,11 +258,11 @@ public IActionResult GetFrameworkGroupsTree()
[HttpGet("GetUserById")]
[AllRights]
- public IActionResult GetUserById(string keywords)
+ public async Task GetUserById(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserById").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserById");
}
var users = DC.Set().Where(x => x.ITCode.ToLower().StartsWith(keywords.ToLower())).GetSelectListItems(Wtm, x => x.Name + "(" + x.ITCode + ")", x => x.ITCode);
return Ok(users);
@@ -270,11 +270,11 @@ public IActionResult GetUserById(string keywords)
[HttpGet("GetUserByGroup")]
[AllRights]
- public IActionResult GetUserByGroup(string keywords)
+ public async Task GetUserByGroup(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByGroup").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByGroup");
}
var users = DC.Set().Where(x => x.GroupCode == keywords).Select(x=>x.UserCode).ToList();
return Ok(users);
@@ -282,11 +282,11 @@ public IActionResult GetUserByGroup(string keywords)
[HttpGet("GetUserByRole")]
[AllRights]
- public IActionResult GetUserByRole(string keywords)
+ public async Task GetUserByRole(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByRole").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkuser/GetUserByRole");
}
var users = DC.Set().Where(x => x.RoleCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeListVM.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeListVM.cs
index 6b9464eac..8af432d81 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeListVM.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeListVM.cs
@@ -130,7 +130,7 @@ public override void AfterDoSearcher()
Dictionary groupdata = new Dictionary();
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- var dd = Wtm.CallAPI>("mainhost", "/api/_account/GetFrameworkGroups").Result;
+ var dd = Wtm.CallAPI>("mainhost", "/api/_account/GetFrameworkGroups").GetAwaiter().GetResult();
if(dd.Data != null)
{
foreach (var item in dd.Data)
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeVM.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeVM.cs
index aa3564868..e7ecde6ef 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeVM.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/DataPrivilegeVMs/DataPrivilegeVM.cs
@@ -77,7 +77,7 @@ public override void Validate()
string user = null;
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- var check = Wtm.CallAPI>("mainhost", "/api/_account/GetUserById").Result;
+ var check = Wtm.CallAPI>("mainhost", "/api/_account/GetUserById").GetAwaiter().GetResult();
if (check.Data != null)
{
user = check.Data.Where(x => x.Value.ToString() == Entity.UserCode).Select(x => x.Value.ToString()).FirstOrDefault();
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupVM.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupVM.cs
index 30326329f..0a7a93357 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupVM.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkGroupVMs/FrameworkGroupVM.cs
@@ -34,13 +34,13 @@ public override void Validate()
public override void DoAdd()
{
base.DoAdd();
- Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override void DoEdit(bool updateAllFields = false)
{
base.DoEdit(updateAllFields);
- Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveGroupCache(LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override async Task DoDeleteAsync()
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM2.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM2.cs
index 3550ccff2..9602caa94 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM2.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkMenuVMs/FrameworkMenuVM2.cs
@@ -269,7 +269,7 @@ public void AddPrivilege(List menuids)
}
}
DC.SaveChanges();
- Wtm.RemoveUserCacheByRole(SelectedRolesCodes.ToArray()).Wait();
+ Wtm.RemoveUserCacheByRole(SelectedRolesCodes.ToArray()).GetAwaiter().GetResult();
}
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM2.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM2.cs
index b79eb180a..db256d4ad 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM2.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleMDVM2.cs
@@ -24,7 +24,7 @@ protected override FrameworkRole GetById(object Id)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Wtm.CallAPI("mainhost", $"/api/_frameworkrole/{Id}").Result.Data.Entity;
+ return Wtm.CallAPI("mainhost", $"/api/_frameworkrole/{Id}").GetAwaiter().GetResult().Data.Entity;
}
else
{
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleVM.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleVM.cs
index 8066549fb..64b22fff4 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleVM.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkRoleVMs/FrameworkRoleVM.cs
@@ -21,13 +21,13 @@ public override DuplicatedInfo SetDuplicatedCheck()
public override void DoAdd()
{
base.DoAdd();
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override void DoEdit(bool updateAllFields = false)
{
base.DoEdit(updateAllFields);
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).GetAwaiter().GetResult();
}
public override async Task DoDeleteAsync()
diff --git a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkTenantVMs/FrameworkTenantVM.cs b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkTenantVMs/FrameworkTenantVM.cs
index 3b3ca2681..4620f5433 100644
--- a/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkTenantVMs/FrameworkTenantVM.cs
+++ b/demo/WalkingTec.Mvvm.ReactDemo/Areas/_Admin/ViewModels/FrameworkTenantVMs/FrameworkTenantVM.cs
@@ -79,7 +79,7 @@ private void TenantOperation()
if (tenantdc.Database.EnsureCreated() == true)
{
tenantdc.SetTenantCode(Entity.TCode);
- tenantdc.DataInit(Wtm.GlobaInfo.AllModule, Wtm.GlobaInfo.IsSpa).Wait();
+ tenantdc.DataInit(Wtm.GlobaInfo.AllModule, Wtm.GlobaInfo.IsSpa).GetAwaiter().GetResult();
}
AddTenantData(tenantdc, fps);
}
@@ -127,7 +127,7 @@ private void AddTenantData(IDataContext dc, List fps)
}
dc.SaveChanges();
var key = $"{GlobalConstants.CacheKey.UserInfo}:{"admin" + "$`$" + Entity.TCode}";
- Cache.DeleteAsync(key).Wait();
+ Cache.DeleteAsync(key).GetAwaiter().GetResult();
}
public override void DoDelete()
{
diff --git a/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/AccountController.cs b/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/AccountController.cs
index 42c9aeb95..396a9fc98 100644
--- a/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/AccountController.cs
+++ b/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/AccountController.cs
@@ -138,9 +138,9 @@ public IActionResult Reg(SimpleReg regInfo)
[HttpPost("[action]")]
[AllRights]
[ProducesResponseType(typeof(Token), StatusCodes.Status200OK)]
- public IActionResult RefreshToken(string refreshToken)
+ public async Task RefreshToken(string refreshToken)
{
- var rv = Wtm.RefreshToken();
+ var rv = await Wtm.RefreshTokenAsync();
if (rv == null)
{
return BadRequest();
@@ -197,11 +197,11 @@ public IActionResult CheckUserInfo(bool IsApi = true)
[AllRights]
[HttpPost("[action]")]
- public IActionResult ChangePassword(ChangePasswordVM vm)
+ public async Task ChangePassword(ChangePasswordVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (!ModelState.IsValid)
{
@@ -242,11 +242,11 @@ public async Task Logout()
[HttpGet("GetFrameworkRoles")]
[ActionDescription("GetRoles")]
[AllRights]
- public IActionResult GetFrameworkRoles()
+ public async Task GetFrameworkRoles()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkRoles").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkRoles");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.RoleName, x => x.RoleCode));
}
@@ -254,11 +254,11 @@ public IActionResult GetFrameworkRoles()
[HttpGet("GetFrameworkGroups")]
[ActionDescription("GetGroups")]
[AllRights]
- public IActionResult GetFrameworkGroups()
+ public async Task GetFrameworkGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -266,11 +266,11 @@ public IActionResult GetFrameworkGroups()
[HttpGet("GetFrameworkGroupsTree")]
[ActionDescription("GetGroupsTree")]
[AllRights]
- public IActionResult GetFrameworkGroupsTree()
+ public async Task GetFrameworkGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetFrameworkGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
@@ -278,11 +278,11 @@ public IActionResult GetFrameworkGroupsTree()
[HttpGet("GetUserById")]
[AllRights]
- public IActionResult GetUserById(string keywords)
+ public async Task GetUserById(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserById").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserById");
}
var users = DC.Set().Where(x => x.ITCode.ToLower().StartsWith(keywords.ToLower())).GetSelectListItems(Wtm, x => x.Name + "(" + x.ITCode + ")", x => x.ITCode);
return Ok(users);
@@ -290,11 +290,11 @@ public IActionResult GetUserById(string keywords)
[HttpGet("GetUserByGroup")]
[AllRights]
- public IActionResult GetUserByGroup(string keywords)
+ public async Task GetUserByGroup(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserByGroup").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserByGroup");
}
var users = DC.Set().Where(x => x.GroupCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
@@ -302,11 +302,11 @@ public IActionResult GetUserByGroup(string keywords)
[HttpGet("GetUserByRole")]
[AllRights]
- public IActionResult GetUserByRole(string keywords)
+ public async Task GetUserByRole(string keywords)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_account/GetUserByRole").Result;
+ return await Request.RedirectCall(Wtm, "/api/_account/GetUserByRole");
}
var users = DC.Set().Where(x => x.RoleCode == keywords).Select(x => x.UserCode).ToList();
return Ok(users);
diff --git a/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/DataPrivilegeController.cs b/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/DataPrivilegeController.cs
index 0521d7d46..63b3187d1 100644
--- a/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/DataPrivilegeController.cs
+++ b/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/DataPrivilegeController.cs
@@ -137,22 +137,22 @@ public ActionResult GetPrivileges()
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetUserGroups()
+ public async Task GetUserGroups()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroups").Result;
+ return await Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroups");
}
return Ok(DC.Set().GetSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetUserGroupsTree()
+ public async Task GetUserGroupsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroupsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_DataPrivilege/GetUserGroupsTree");
}
return Ok(DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName, x => x.GroupCode));
}
diff --git a/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkGroupController.cs b/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkGroupController.cs
index 607479b1e..ba8cb3f6f 100644
--- a/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkGroupController.cs
+++ b/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkGroupController.cs
@@ -19,11 +19,11 @@ public class FrameworkGroupController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkGroupSearcher searcher)
+ public async Task Search(FrameworkGroupSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -128,7 +128,7 @@ public async Task BatchDelete(string[] ids)
DC.Set().RemoveRange(gr);
DC.SaveChanges();
await Wtm.RemoveUserCacheByGroup(GroupCode.ToArray());
- Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(ids.Count());
}
}
@@ -185,7 +185,7 @@ public IActionResult GetExcelTemplate()
[ActionDescription("Sys.Import")]
[HttpPost("[action]")]
- public ActionResult Import(FrameworkGroupImportVM vm)
+ public async Task Import(FrameworkGroupImportVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
@@ -198,18 +198,18 @@ public ActionResult Import(FrameworkGroupImportVM vm)
}
else
{
- Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveGroupCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(vm.EntityList.Count);
}
}
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetParents()
+ public async Task GetParents()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParents").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParents");
}
var data = DC.Set().GetSelectListItems(Wtm, x => x.GroupName);
return Ok(data);
@@ -217,11 +217,11 @@ public IActionResult GetParents()
[AllRights]
[HttpGet("[action]")]
- public IActionResult GetParentsTree()
+ public async Task GetParentsTree()
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParentsTree").Result;
+ return await Request.RedirectCall(Wtm, "/api/_frameworkgroup/GetParentsTree");
}
var data = DC.Set().GetTreeSelectListItems(Wtm, x => x.GroupName);
return Ok(data);
diff --git a/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkRoleController.cs b/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkRoleController.cs
index 62724cfde..ef7ce2a10 100644
--- a/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkRoleController.cs
+++ b/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkRoleController.cs
@@ -19,11 +19,11 @@ public class FrameworkRoleController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkRoleSearcher searcher)
+ public async Task Search(FrameworkRoleSearcher searcher)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
- return Request.RedirectCall(Wtm).Result;
+ return await Request.RedirectCall(Wtm);
}
if (ModelState.IsValid)
{
@@ -216,7 +216,7 @@ public IActionResult GetExcelTemplate()
[ActionDescription("Sys.Import")]
[HttpPost("[action]")]
- public ActionResult Import(FrameworkRoleImportVM vm)
+ public async Task Import(FrameworkRoleImportVM vm)
{
if (ConfigInfo.HasMainHost && Wtm.LoginUserInfo?.CurrentTenant == null)
{
@@ -229,7 +229,7 @@ public ActionResult Import(FrameworkRoleImportVM vm)
}
else
{
- Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant).Wait();
+ await Wtm.RemoveRoleCache(Wtm.LoginUserInfo.CurrentTenant);
return Ok(vm.EntityList.Count);
}
}
diff --git a/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkUserController.cs b/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkUserController.cs
index e213fe8dd..0b9ab286c 100644
--- a/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkUserController.cs
+++ b/demo/WalkingTec.Mvvm.Vue3Demo/Areas/_Admin/Controllers/FrameworkUserController.cs
@@ -20,11 +20,11 @@ public class FrameworkUserController : BaseApiController
{
[ActionDescription("Sys.Search")]
[HttpPost("[action]")]
- public IActionResult Search(FrameworkUserSearcher searcher)
+ public async Task