Activities of "kfrancis@clinicalsupportsystems.com"

Question for you,

We're well into the migration of our service from our old .NET 4.8 Webforms app (servicing 4000 users daily, oof) but we do have one complication that I'm wondering if you could help us with. The main task our app does is automate interation with a remote service. This remote service was such a pain that we developed a .net API wrapper around it and that alone has been a good source of revenue, because whoever designed that API must really hate their job. Anyways, the wrapper does a great job allowing our existing system to interact with the remote service sending and receiving thousands of files daily. The wrapper is WCF, handles creating self-signed certs to satisy the black box requirements, it's great. With our old system, we had a Windows Service that handled connecting to every account every n hours by forking a command line process that did only that and that mostly works but we want to split up sending of files from retreiving of files (our current way introduces great delay for submissions and it's not easily testable whatsoever).

Unfortunately, Microsoft in their wisdom, haven't kept WCF up with .NET 5 so we will need to find a way to allow an AsyncBackgroundJob (to send files created by users) and a AsyncPeriodicBackgroundWorkerBase to connect to that service to submit files and to check the remote service for files available for processing .. somehow.

We can implement the service in a number of ways, we've utilized: azure functions, separate processes, etc but I'm curious to see if you have any suggestions that would a) lend itself to be much more manageable in this solution and b) hopefully allow us to test at least some of it, not likely the actual remote sending but that's fine but at least the queuing and execution of these jobs/workers.

Thoughts?

  • ABP Framework version: v4.2.0 Commercial
  • UI type: MVC
  • DB provider: EF Core / ADO (custom)
  • Tiered (MVC) or Identity Server Seperated (Angular): yes

Perfect, that seems to have done the trick and also (bonus) not required me to split interfaces! Thanks!

So, first - we're using the concept of strongly typed id's from here:

So a simple class of ours might look like:

public class GeneratedReport : GeneratedReportBase<GeneratedReportStatus, GeneratedReportFileType>, IEntity<GeneratedReport_Id>
{
    public GeneratedReport_Id Id { get; set; }
    public int SortOrder { get; set; }
    public object[] GetKeys()
    {
        return new object[] { Id };
    }
}

where GeneratedReport_Id is:

/// <summary>
/// https://andrewlock.net/strongly-typed-id-updates/
/// </summary>
[StronglyTypedId(jsonConverter: StronglyTypedIdJsonConverter.SystemTextJson | StronglyTypedIdJsonConverter.NewtonsoftJson, backingType: StronglyTypedIdBackingType.Guid)]
public partial struct GeneratedReport_Id { }

And that works great. We use tons of guids and in migrating our solution (mix of .net48 with WebForm/Mvc) and we really wanted to enable ourselves to catch errors where Guids were being used incorrectly. To this we had to write a data layer that interacted with the db which was relatively easy to do with the extensibility of abp. The data engineer had everything but the site working (started on abp free, moved to commercial) and now we're at the point that I've created the commercial solution and we're trying to start working on the UI which is primarily Kendo UI based (instead of Datatables). I have a blog post coming about that for the community.

So, on to the method in question. Obviously our app services have interfaces and those interfaces can contain these strongly typed ids:

[HttpPost]
[Route("{id}")]
public Task SaveReportContentAsync(GeneratedReport_Id Id, byte[] ReportContent, CancellationToken cancellationToken = default)
{
    // TODO: Copy implementation
    throw new NotImplementedException();
}

I see that the api-generation code is looking at GeneratedReport_Id and noticing it's not a primitive type so it breaks the inherent rule but ..

Since SaveReportContentAsync is detailed in the IGeneratedReportAppService interface, it's required when creating the GeneratedReportsController in the HttpApi project. Since I only expect the API methods to be able to get lists of reports and not make them (report content is only created by a background job that uses Telerik Reporting), I don't really want that to be part of the API but I don't see any documentation letting me attribute certain methods to ignore them.

  • ABP Framework version: v4.2.0
  • UI type: MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Seperated (Angular): yes
  • Exception message and stack trace:
  • Steps to reproduce the issue: N/A

Is there a way to customize how the auto api is looking at methods, or mark methods with an attribute so that we don't get the usual "Only one complex type allowed as argument to a controller" message without having to split all my app service interfaces just to remove methods that don't work with the auto api?

2021-02-01 16:07:38.495 -05:00 [INF] Executed endpoint 'Volo.Abp.AspNetCore.Mvc.ProxyScripting.AbpServiceProxyScriptController.GetAll (Volo.Abp.AspNetCore.Mvc)'
2021-02-01 16:07:38.496 -05:00 [INF] AUDIT LOG: [200: GET    ] /Abp/ServiceProxyScript
- UserName - UserId                 : admin - fa5c8917-753d-f0bd-9ac6-39fa5bf3f2aa
- ClientIpAddress        : ::1
- ExecutionDuration      : 43

2021-02-01 16:07:38.496 -05:00 [ERR] An unhandled exception has occurred while executing the request.
Volo.Abp.AbpException: Only one complex type allowed as argument to a controller action that's binding source is 'Body'. But SaveReportContentAsync (api/app/generatedreport/{id}) contains more than one!
   at Volo.Abp.Http.ProxyScripting.Generators.ProxyScriptingHelper.GenerateBody(ActionApiDescriptionModel action)
   at Volo.Abp.Http.ProxyScripting.Generators.JQuery.JQueryProxyScriptGenerator.AddAjaxCallParameters(StringBuilder script, ActionApiDescriptionModel action)
   at Volo.Abp.Http.ProxyScripting.Generators.JQuery.JQueryProxyScriptGenerator.AddActionScript(StringBuilder script, String controllerName, ActionApiDescriptionModel action, String normalizedActionName)
   at Volo.Abp.Http.ProxyScripting.Generators.JQuery.JQueryProxyScriptGenerator.AddControllerScript(StringBuilder script, ControllerApiDescriptionModel controller)
   at Volo.Abp.Http.ProxyScripting.Generators.JQuery.JQueryProxyScriptGenerator.AddModuleScript(StringBuilder script, ModuleApiDescriptionModel module)
   at Volo.Abp.Http.ProxyScripting.Generators.JQuery.JQueryProxyScriptGenerator.CreateScript(ApplicationApiDescriptionModel model)
   at Volo.Abp.Http.ProxyScripting.ProxyScriptManager.CreateScript(ProxyScriptingModel scriptingModel)
   at Volo.Abp.Http.ProxyScripting.ProxyScriptManager.<>c__DisplayClass6_0.<GetScript>b__0()
   at System.Collections.Generic.AbpDictionaryExtensions.<>c__DisplayClass6_0`2.&lt;GetOrAdd&gt;b__0(TKey k)
   at System.Collections.Generic.AbpDictionaryExtensions.GetOrAdd[TKey,TValue](IDictionary`2 dictionary, TKey key, Func`2 factory)
   at System.Collections.Generic.AbpDictionaryExtensions.GetOrAdd[TKey,TValue](IDictionary`2 dictionary, TKey key, Func`1 factory)
   at Volo.Abp.Http.ProxyScripting.ProxyScriptManagerCache.GetOrAdd(String key, Func`1 factory)
   at Volo.Abp.Http.ProxyScripting.ProxyScriptManager.GetScript(ProxyScriptingModel scriptingModel)
   at Volo.Abp.AspNetCore.Mvc.ProxyScripting.AbpServiceProxyScriptController.GetAll(ServiceProxyGenerationModel model)
   at lambda_method1950(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResourceFilter()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Volo.Abp.AspNetCore.Serilog.AbpSerilogMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Volo.Abp.AspNetCore.MultiTenancy.MultiTenancyMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.RequestLocalization.AbpRequestLocalizationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
2021-02-01 16:07:38.497 -05:00 [INF] Request finished HTTP/2 GET https://localhost:44311/Abp/ServiceProxyScript - - - 500 - text/plain 45.2770ms

@alper Thank you, we appreciate that change. We very much understand in general the reason behind that initial decision, but much of this is what people need to do to properly implement abp/abp-commericial in their product. Between that and more theme documents, we love what you're doing.

This is a bit crazy. So, we buy Team license and we can't change from the fontawesome free icons to the pro? What? I just want to make some adjustments here ..

Showing 51 to 56 of 56 entries
Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11