I have a .net 6 solution that has two Service Fabric stateless services. The first one "ServiceA" is a web service that receives incoming API requests and then it creates a proxy to second one "ServiceB" that is deployed in the same cluster. The problem is, the when the proxy is created and I try to access the method that ServiceB implements, I get this exception:
"message": "System.AggregateException: One or more errors occurred. (Common Language Runtime detected an invalid program.)
---> System.InvalidProgramException: Common Language Runtime detected an invalid program.
at ServiceB.Contracts.Infrastructure.IServiceB_.service.disp.IServiceBMethodDispatcher.OnDispatchAsync(Int32 , Object , IServiceRemotingRequestMessageBody , IServiceRemotingMessageBodyFactory , CancellationToken )
at Microsoft.ServiceFabric.Services.Remoting.V2.Builder.MethodDispatcherBase.DispatchAsync(Object objectImplementation, Int32 methodId, IServiceRemotingRequestMessageBody requestBody, IServiceRemotingMessageBodyFactory remotingMessageBodyFactory, CancellationToken cancellationToken)
at Microsoft.ServiceFabric.Services.Remoting.V2.Runtime.ServiceRemotingMessageDispatcher.OnDispatch(IServiceRemotingRequestMessageHeader requestMessageHeaders, IServiceRemotingRequestMessageBody requestBody, CancellationToken cancellationToken)
--- End of stack trace from previous location ---
at Microsoft.ServiceFabric.Services.Remoting.V2.Runtime.ServiceRemotingMessageDispatcher.OnDispatch(IServiceRemotingRequestMessageHeader requestMessageHeaders, IServiceRemotingRequestMessageBody requestBody, CancellationToken cancellationToken)
at Microsoft.ServiceFabric.Services.Remoting.V2.Runtime.ServiceRemotingMessageDispatcher.<>c__DisplayClass8_1.<HandleRequestResponseAsync>
b__0(CancellationToken cancellationToken)
at Microsoft.ServiceFabric.Services.Remoting.Runtime.ServiceRemotingCancellationHelper.DispatchRequest[T](Int32 interfaceId, Int32 methodId, String callContext, Func`2 dispatchFunc)
at Microsoft.ServiceFabric.Services.Remoting.V2.Runtime.ServiceRemotingMessageDispatcher.HandleRequestResponseAsync(IServiceRemotingRequestContext requestContext, IServiceRemotingRequestMessage requestMessage)\r\n at Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime.FabricTransportMessageHandler.RequestResponseAsync(FabricTransportRequestContext requestContext, FabricTransportMessage fabricTransportMessage)
--- End of inner exception stack trace ---
at Microsoft.ServiceFabric.Services.Communication.Client.ServicePartitionClient`1.InvokeWithRetryAsync[TResult](Func`2 func, CancellationToken cancellationToken, Type[] doNotRetryExceptionTypes)\r\n at Microsoft.ServiceFabric.Services.Remoting.V2.Client.ServiceRemotingPartitionClient.InvokeAsync(IServiceRemotingRequestMessage remotingRequestMessage, String methodName, CancellationToken cancellationToken)
at Microsoft.ServiceFabric.Services.Remoting.Builder.ProxyBase.InvokeAsyncV2(Int32 interfaceId, Int32 methodId, String methodName, IServiceRemotingRequestMessageBody requestMsgBodyValue, CancellationToken cancellationToken)
at Microsoft.ServiceFabric.Services.Remoting.Builder.ProxyBase.ContinueWithResultV2[TRetval](Int32 interfaceId, Int32 methodId, Task`1 task)\r\n at MyApp.WebService.Proxies.ServiceBProxy.IsSomeStuffInProgressAsync() in C:\\dev\\repos\my-sf-app\\MyApp.WebService\\Proxies\\ServiceBProxy.cs:line 21
at MyApp.WebService.Controllers.FileController.CheckSomeStuffState() in C:\\dev\\repos\my-sf-app\\MyApp.WebService\\Controllers\\FileController.cs:line 44
... and some other bits"
This is how the proxy is crated in ServiceA:
public class ServiceBServiceProxy : IServiceB
{
private const string ServiceBUri = "fabric:/MyApp.ServiceB/ServiceBService";
public async Task<bool> IsSomeStuffInProgressAsync()
{
var proxy = ServiceProxy.Create<IServiceB>(new Uri(ServiceBUri));
return await proxy.IsSomeStuffInProgressAsync().ConfigureAwait(false); -- error thrown at this poit
}
}
Interface that is implemented in both services ServiceA and ServiceB
public interface IServiceB : IService
{
Task<bool> IsSomeStuffInProgressAsync();
}
IService implementation is ServiceB:
internal sealed class ServiceB : StatelessService, IServiceB
{
private readonly Container _container;
public ServiceB(StatelessServiceContext context, Container container)
: base(context)
{
_container = container;
}
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return this.CreateServiceRemotingInstanceListeners();
}
public async Task<bool> IsSomeStuffInProgressAsync()
{
await using (AsyncScopedLifestyle.BeginScope(_container))
{
var someService = _container.GetService<SomeService>();
return await someService.CheckSomeStuff().ConfigureAwait(false);
}
}
}
Please note, this error is thrown in local environment and on real Test server. Any ideas are appreciated, thanks! Let me know if I need to populate this question with more details.
SF package versions match in both services.
<PackageReference Include="Microsoft.ServiceFabric.Services" Version="3.3.638" />
<PackageReference Include="Microsoft.ServiceFabric.Services.Remoting" Version="3.3.638" />
<PackageReference Include="Microsoft.ServiceFabric.AspNetCore.Kestrel" Version="3.3.638" /> - in WebService (ServiceA)
Both services are successfully deployed to SF cluster. Currently I use the remoting version 1. I did try updating it to version 2 but I go exactly same error in the end.
I tried disabling code optimization and enabling support for 32-bit apps but that didn't help as well.
Originally, the ServiceB was stateful but now I converted it to stateless. There were some net framework 4.8 class libraries but all of them were converted to .net 6 and all dependencies were updated/resolved as well. Not sure what was else needs to be done to make this work. All the code looks pretty the same as in this MS documentation https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication-remoting
Related
I have an issue in async WCF service using SoapCore in .Net 6 using a cancellation token and XmlSerializer serializer.
The detailed WCF application is as follows:
WCF service in C# .Net Core 6 using SoapCore NuGet package using SoapSerializer.XmlSerializer serializer
I created an async method that has the [OperationContract] attribute with a CancellationToken parameter
I try to get the WSDL using the URL https://localhost:7026/Services.svc?WSDL and it fails because of the CancellationToken with the exception ArgumentException: .NET type CancellationToken cannot be resolved into XML schema type (CancellationToken has namespace starting with System (System.Threading.CancellationToken), is a structure (value type), and is categorized by SoapCore code as very similar to bool, int, long, ... and tries to generate an XML for it and it fails)
I tried adding the [XmlIgnore] attribute to the parameter CancellationToken of the method having the [OperationContract] attribute and it doesn't work
[MessageContract(IsWrapped = false)] cannot be added to parameters of methods
Note: This works with SoapCore with SoapSerializer.DataContractSerializer serializer, but the generated WSDL is bigger enumerating many basic types that I don't use and I want to use SoapSerializer.XmlSerializer if possible.
Program.cs code:
using Microsoft.Extensions.DependencyInjection.Extensions;
using SoapCore;
namespace TestSoapCore;
public static class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSoapCore();
builder.Services.TryAddSingleton<MyService>();
builder.Services.AddMvc();
var app = builder.Build();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.UseSoapEndpoint<MyService>(
"/Services.svc",
new SoapEncoderOptions(),
SoapSerializer.XmlSerializer
// This works with SoapSerializer.DataContractSerializer but I prefer SoapSerializer.XmlSerializer if possible
);
});
app.Run();
}
}
Contract.cs code:
using System.Runtime.Serialization;
namespace TestSoapCore;
[DataContract]
public class Contract {
[DataMember]
public string? TestProperty { get; set; }
}
MyService.cs code:
using System.ServiceModel;
using System.Xml.Serialization;
namespace TestSoapCore;
[ServiceContract]
public class MyService
{
[OperationContract]
public async Task<string> Test(
Contract contract,
// [MessageContract(IsWrapped = false)] cannot be added to parameters
[XmlIgnore] // This doesn't work
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
return contract?.TestProperty + "2";
}
}
Full exception while getting the WSDL at https://localhost:7026/Services.svc?WSDL when SoapSerializer.XmlSerializer serializer is used:
How the WSDL works with SoapSerializer.XmlSerializer serializer without any CancellationToken (but I want the CancellationToken for async methods, it is better to have it):
How the WSDL is bloated and has many basic types I don't use when SoapSerializer.DataContractSerializer serializer is used (that's why I still prefer SoapSerializer.XmlSerializer if possible):
Part 1:
Part 2:
Part 3:
Part 4:
Like Aleksander Ch response, but mixed with the example of official page
Interface
[ServiceContract]
public interface IService
{
public void SetCancellationToken(CancellationToken cancellationToken);
[OperationContract]
public Task<int> CheckStatus();
}
Service (Very important ThreadLocal variable)
public sealed class Service : IService
{
private readonly ThreadLocal<CancellationToken> _threadCancellationToken = new();
Task<int> ILectoService.CheckStatus()
{
if (_threadCancellationToken.IsValueCreated)
_threadCancellationToken.Value.ThrowIfCancellationRequested();
........
}
void ILectoService.SetCancellationToken(CancellationToken cancellationToken)
{
_threadCancellationToken.Value = cancellationToken;
}
}
ServiceOperationTuner
internal sealed class ServiceOperationTuner : IServiceOperationTuner
{
public void Tune(HttpContext httpContext, object serviceInstance, SoapCore.ServiceModel.OperationDescription operation)
{
if (serviceInstance is IService service)
{
service.SetCancellationToken(httpContext.RequestAborted);
}
}
}
Add service operation tuner in Program
builder.Services.AddSoapServiceOperationTuner(new ServiceOperationTuner());
Because the CancellationToken is not working very well with WCF using SoapCore (SoapSerializer.XmlSerializer serializer doesn't generate the WSDL because of CancellationToken and SoapSerializer.DataContractSerializer serializer puts the CancellationToken as an object that needs to be sent with many properties and their types) I ended up removing the CancellationToken entirely and I used the SoapSerializer.XmlSerializer to have less data (WSDL not bloated with all the unused types, many pages of useless data).
PS: This is how the CancellationToken looks with SoapCore and SoapSerializer.DataContractSerializer serializer (not very nice..):
If You want to get SoapCore working with cancellation token there is another approach. SoapCore allows us to define ServiceOperationTuner which can read the cancellationToken from HttpContext and than assign it to service. The example bellow explains the idea of sollution
Define service operation tuner
public class ServiceOperationTuner : IServiceOperationTuner
{
public void Tune(HttpContext httpContext, object serviceInstance, OperationDescription operation)
{
if (serviceInstance != null && serviceInstance is MyService)
{
MyService service = serviceInstance as MyService;
service.SetCancellationToken(httpContext.RequestAborted);
}
}
}
Add service operation tuner in Program
builder.Services.AddSoapServiceOperationTuner(new ServiceOperationTuner());
Modify MyService in order to get cancellationToken
public class MyService
{
CancellationToken _cancellationToken;
public void SetCancellationToken(CancellationToken cancellationToken)
{
_cancellationToken = cancellationToken;
}
I have been going crazy this last days.
I'm trying to use string Guids as _id's in my MongoDb, with the latest version of the driver. I stumbled with this tutorial, which shed me some light...
Storing GUIDs as strings in MongoDB with C#
But I am getting this error: FormatException: Cannot deserialize a 'Guid' from BsonType 'ObjectId'.
MongoDB.Bson.Serialization.Serializers.GuidSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
MongoDB.Bson.Serialization.Serializers.SerializerBase<TValue>.MongoDB.Bson.Serialization.IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize(IBsonSerializer serializer, BsonDeserializationContext context)
MongoDB.Bson.Serialization.BsonClassMapSerializer<TClass>.DeserializeMemberValue(BsonDeserializationContext context, BsonMemberMap memberMap)
The stack trace:
at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeMemberValue(BsonDeserializationContext context, BsonMemberMap memberMap)
at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeClass(BsonDeserializationContext context)
at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context)
at MongoDB.Driver.Core.Operations.CursorBatchDeserializationHelper.DeserializeBatch[TDocument](RawBsonArray batch, IBsonSerializer`1 documentSerializer, MessageEncoderSettings messageEncoderSettings)
at MongoDB.Driver.Core.Operations.FindCommandOperation`1.CreateFirstCursorBatch(BsonDocument cursorDocument)
at MongoDB.Driver.Core.Operations.FindCommandOperation`1.CreateCursor(IChannelSourceHandle channelSource, BsonDocument commandResult)
at MongoDB.Driver.Core.Operations.FindCommandOperation`1.Execute(RetryableReadContext context, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.FindOperation`1.Execute(RetryableReadContext context, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.FindOperation`1.Execute(IReadBinding binding, CancellationToken cancellationToken)
at MongoDB.Driver.OperationExecutor.ExecuteReadOperation[TResult](IReadBinding binding, IReadOperation`1 operation, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperation[TResult](IClientSessionHandle session, IReadOperation`1 operation, ReadPreference readPreference, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperation[TResult](IClientSessionHandle session, IReadOperation`1 operation, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass45_0`1.<FindSync>b__0(IClientSessionHandle session)
at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
at MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.AsyncCursorSourceEnumerableAdapter`1.GetEnumerator()
at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
at System.Linq.SystemCore_EnumerableDebugView`1.get_Items()
I've scoured the Internet in search of an answer.
I DO NOT WANT TO USE POCO's DECORATION, OR RETURN BsonDocuments. Already went this route:
BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;
BsonSerializer.RegisterSerializer<Guid>(new GuidSerializer(GuidRepresentation.Standard));
and didn't work. Also did the convention thing...
public class GuidAsStringRepresentationConvention : ConventionBase, IMemberMapConvention
{
public void Apply(BsonMemberMap memberMap)
{
if (memberMap.MemberType == typeof(Guid))
memberMap.SetSerializer(new GuidSerializer(BsonType.String));
else if (memberMap.MemberType == typeof(Guid?))
memberMap.SetSerializer(new NullableSerializer<Guid>(new GuidSerializer(BsonType.String)));
}
}
Didn't work either...
This is my code:
public class TestClass
{
public Guid Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
}
This gets called BEFORE the Db connection:
if (!BsonClassMap.IsClassMapRegistered(typeof(TestClass)))
{
BsonClassMap.RegisterClassMap<TestClass>(cm =>
{
cm.MapIdMember(m => m.Id).SetOrder(0);
cm.MapMember(m => m.Name).SetOrder(1);
cm.MapMember(m => m.IsActive).SetOrder(2);
});
}
var conn = configuration.GetConnectionString("MongoDb");
var name = MongoUrl.Create(conn).DatabaseName;
var client = new MongoClient(conn);
_db = client.GetDatabase(name);
after that, I try to get the records, after I initialize the collection in the constructor...
public async Task<IEnumerable<TestClass>> ReadAllAsync(CancellationToken cancellationToken = default)
{
var filter = Builders<TestClass>.Filter.Empty;
var items = await _collection.Find<TestClass>(filter).ToListAsync(cancellationToken: cancellationToken);
return items;
}
And of course, I initialize the serializer on "ConfigureServices" in the Startup.cs
BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String));
Last, the BSON document with the string GUID (or UUID):
{
"_id" : "c2ea54fc-3942-4ad5-8315-9e96cc5de034",
"name" : "I'm Going Crazy",
"isActive" : true
}
If anyone can shed some light, I would appreciate it a lot. Thanks!!!!
[UPDATE]
I did this:
var col = _db.GetCollection<BsonDocument>("TestCollection");
var list = col.Find(FilterDefinition<BsonDocument>.Empty).ToList();
...and I can see the string GUIDs, everything loads perfectly. It's just NOT PARSING correctly. AND I DON'T KNOW WHY. And I refuse to parse this document manually!!!! That's what the driver is supposed to be doing!
[UPDATE 2]
Decided to decorate the property with:
[BsonId]
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
public Guid Id { get; set; }
Didn't work either...
If you want to keep using Guids natively (rather than treating them as strings), change the serializer you are registering.
Remove:
BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String));
And replace it with:
BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;
Yes, the second line (at time of writing), is an obsolete method, but for now it's the only way to do it. It's an open bug with the c# driver.
There does seem to be an issue here that needs to be fixed.
In the long run we encourage everyone to use the new V3 GuidRepresentationMode, and in fact when using V3 mode this bug does not appear to happen. I added the following line of code as the first line of main:
BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;
We still need to figure out how to get your code to work in V2 mode, but if you are willing to use V3 mode you could have an immediate workaround.
Apparently, the GUIDs I was using were not valid GUIDs. I generated them using an online generator.
I generated new ones on another website, and voilá. Everyting worked.
I have downloaded .NET Core + Vue template for ASP.NET Boilerplate (v3.7.0).
I added:
code by referencing http://aspnetboilerplate.com/Pages/Documents/Quartz-Integration.
NuGet Abp.Quartz in xxx.Application project.
MyAbpQuartzModule.cs, MyLogJob.cs in xxx.Application project:
[DependsOn(typeof(AbpAutoMapperModule), typeof(AbpQuartzModule))]
public class MyAbpQuartzModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
MyAbpQuartzController.cs in xxx.Web.Host project:
public class MyAbpQuartzController : AbpController
{
private readonly IQuartzScheduleJobManager _jobManager;
public MyAbpQuartzController(IQuartzScheduleJobManager jobManager)
{
_jobManager = jobManager;
}
public async Task<ActionResult> ScheduleJobWithTask()
{
await _jobManager.ScheduleAsync<MyLogJob>(
job =>
{
job.WithIdentity("MyLogJobIdentity", "MyGroup")
.WithDescription("A job to simply write logs.");
},
trigger =>
{
trigger.StartNow()
.WithSimpleSchedule(schedule =>
{
schedule.RepeatForever()
.WithIntervalInSeconds(5)
.Build();
});
});
return Content("OK, scheduled!");
}
public ContentResult TestMyAbpQuartz(string message = "")
{
return Content("OK, scheduled!");
}
}
I debugged the xxx.Web.Host project, but it didn't work.
The http://localhost:21021/MyAbpQuartz/TestMyAbpQuartz page returned:
"This page isn’t working
localhost is currently unable to handle this request.
HTTP ERROR 500"
I think that QuartzScheduleJobManager didn't register successfully.
So, what should I do?
Part of error message in Web.Host/App_Data/log.txt:
ERROR 2018-06-08 19:19:04,161 [5 ] Mvc.ExceptionHandling.AbpExceptionFilter - Can't create component 'MyNetCoreWithVueProject.Web.Host.Controllers.MyAbpQuartzController' as it has dependencies to be satisfied.
'MyNetCoreWithVueProject.Web.Host.Controllers.MyAbpQuartzController' is waiting for the following dependencies:
- Service 'Abp.Quartz.IQuartzScheduleJobManager' which was not registered.
Castle.MicroKernel.Handlers.HandlerException: Can't create component 'MyNetCoreWithVueProject.Web.Host.Controllers.MyAbpQuartzController' as it has dependencies to be satisfied.
'MyNetCoreWithVueProject.Web.Host.Controllers.MyAbpQuartzController' is waiting for the following dependencies:
- Service 'Abp.Quartz.IQuartzScheduleJobManager' which was not registered.
at Castle.MicroKernel.Handlers.DefaultHandler.AssertNotWaitingForDependency()
at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden)
at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired)
at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy)
at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
at Castle.Windsor.MsDependencyInjection.ScopedWindsorServiceProvider.GetServiceInternal(Type serviceType, Boolean isOptional) in D:\Github\castle-windsor-ms-adapter\src\Castle.Windsor.MsDependencyInjection\ScopedWindsorServiceProvider.cs:line 55
at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
INFO 2018-06-08 19:19:04,967 [5 ] ore.Mvc.Internal.ControllerActionInvoker - Executed action MyNetCoreWithVueProject.Web.Host.Controllers.MyAbpQuartzController.TestMyAbpQuartz (MyNetCoreWithVueProject.Web.Host) in 833.6801ms
ERROR 2018-06-08 19:19:05,059 [5 ] Microsoft.AspNetCore.Server.Kestrel - Connection id "0HLED66DNH26L", Request id "0HLED66DNH26L:00000004": An unhandled exception was thrown by the application.
Castle.MicroKernel.Handlers.HandlerException: Can't create component 'MyNetCoreWithVueProject.Web.Host.Controllers.MyAbpQuartzController' as it has dependencies to be satisfied.
IQuartzScheduleJobManager should be registered by AbpQuartzModule.
I see that you already have [DependsOn(typeof(AbpQuartzModule))] on MyAbpQuartzModule.
Add [DependsOn(typeof(MyAbpQuartzModule))] to *WebHostModule:
[DependsOn(
typeof(AbpProjectNameWebCoreModule),
typeof(MyAbpQuartzModule))]
public class AbpProjectNameWebHostModule : AbpModule
If you want to register a specific class that does not fit into the conventional registration rules. ASP.NET Boilerplate provides the ITransientDependency, the IPerWebRequestDependency and the ISingletonDependency interfaces as a shortcut.
public interface IQuartzScheduleJobManager
{
//...
}
public class QuartzScheduleJobManager: IQuartzScheduleJobManager, ITransientDependency
{
//...
}
I'm currently working with Azure Functions and I just found this interface definition.
Assembly Microsoft.Extensions.Logging.Abstractions, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
using System;
namespace Microsoft.Extensions.Logging
{
public interface ILogger
{
IDisposable BeginScope<TState>(TState state);
bool IsEnabled(LogLevel logLevel);
void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter);
}
}
I am particular interested in void Log<TState>. This function has what looks like a generic, but seems to magically expand into 6 functions.
log.LogCritical("...");
log.LogDebug("...");
log.LogError("...");
log.LogInformation("...");
log.LogTrace("...");
log.LogWarning("...");
I receive the reference to log via the Azure Function defintion.
[FunctionName("WhoAmI")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req, ILogger log)
{ ... }
The Microsoft samples and documentation reflect this.
I'm guessing this is a C# or Visual Studio feature and not witchcraft, but which feature is it?
This is C# feature called Extension Methods. These methods are defined in LoggerExtensions static class. Here is a sample signature:
public static void LogDebug (
this ILogger logger, EventId eventId, string message, object[] args);
It's the keyword this which makes the call look like it's the member of interface.
LoggerExtensions class.
C# Extension methods.
Credits to #SirRufo for giving the right hint in the comments. I just don't want to leave this question without the full answer :)
I'm new to NServiceBus (and a green developer) and I'm getting destroyed by this exception (in the NSB console, before calling the handler):
2014-02-26 14:27:10,269 [8] ERROR NServiceBus.Unicast.Transport.TransportReceiver [(null)] <(null)> -
Failed to deserialize message with ID: b0e459fa-0ada-431c-bbee-a2de00ee2a29
System.Runtime.Serialization.SerializationException: An error occurred while attempting to extract logical messages
from transport message NServiceBus.TransportMessage ---> System.ArgumentNullException: Value cannot be null.
Parameter name: path
at System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional)
at System.Security.Permissions.FileIOPermission.AddPathList(FileIOPermissionA
ccess access, AccessControlActions control, String[] pathListOrig, Boolean check
ForDuplicates, Boolean needFullPath, Boolean copyPathList)
at System.IO.FileSystemInfo.set_Attributes(FileAttributes value)
at SetIsReadOnly(Object , Object )
at NServiceBus.Serializers.XML.XmlMessageSerializer.GetObjectOfTypeFromNode(T
ype t, XmlNode node) in c:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceBus.Core
\Serializers\XML\XmlMessageSerializer.cs:line 492
at NServiceBus.Serializers.XML.XmlMessageSerializer.GetPropertyValue(Type typ
e, XmlNode n) in c:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceBus.Core\Serial
izers\XML\XmlMessageSerializer.cs:line 828
at NServiceBus.Serializers.XML.XmlMessageSerializer.GetObjectOfTypeFromNode(T
ype t, XmlNode node) in c:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceBus.Core
\Serializers\XML\XmlMessageSerializer.cs:line 487
at NServiceBus.Serializers.XML.XmlMessageSerializer.Process(XmlNode node, Obj
ect parent, Type nodeType) in c:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceBu
s.Core\Serializers\XML\XmlMessageSerializer.cs:line 379
at NServiceBus.Serializers.XML.XmlMessageSerializer.Deserialize(Stream stream
, IList`1 messageTypesToDeserialize) in c:\BuildAgent\work\31f8c64a6e8a2d7c\src\
NServiceBus.Core\Serializers\XML\XmlMessageSerializer.cs:line 359
at NServiceBus.Unicast.Messages.ExtractLogicalMessagesBehavior.Extract(Transp
ortMessage physicalMessage) in c:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceB
us.Core\Unicast\Messages\ExtractLogicalMessagesBehavior.cs:line 74
at NServiceBus.Unicast.Messages.ExtractLogicalMessagesBehavior.Invoke(Receive
PhysicalMessageContext context, Action next) in c:\BuildAgent\work\31f8c64a6e8a2
d7c\src\NServiceBus.Core\Unicast\Messages\ExtractLogicalMessagesBehavior.cs:line
52
--- End of inner exception stack trace ---
I got the MVC Example project working from the free chapters, but I couldn't get the pubsub example to work because 'Host doesn't support hosting of multiple endpoints.'
I'm working in 3 projects in my broken solution, just trying to get a simple 1-node pub and 1-node sub going:
Core (NServiceBus.Interfaces 4.4.1 from NuGet, contains Events folder with IFileUploadedEvent.cs)
FileWatcherService (NServiceBus.Host 4.4.1 from NuGet)
FileMoverService (NServiceBus.Host 4.4.1 from NuGet)
Core\Events\IFileUploadedEvent.cs:
using NServiceBus;
using ...
namespace Core.Events
{ public interface IFileUploadedEvent : IEvent
{ Guid EventId { get; set; }
string Client { get; set; }
FileInfo FileName { get; set; }
}
}
FileWatcherService has default app.config, no mappings.
FileWatcherService.EndpointConfig.cs:
namespace FileWatcherService
{ using NServiceBus;
public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher {}
}
FileWatcherService.FileWatcher.cs:
using NServiceBus;
using Core.Events;
using ...
namespace FileWatcherService
{ public class FileWatcher : IWantToRunWhenBusStartsAndStops
{ public IBus Bus { get; set; }
public void Activate()
{ ... }
...Stalker, calls PublishFileUploaded
public void PublishFileUploaded(FileInfo fileName, string clientName)
{ Bus.Publish<IFileUploadedEvent>(evt =>
{ evt.EventId = Guid.NewGuid();
evt.Client = clientName;
evt.FileName = fileName;
});
} } }
the FileMoverService.App.config contains:
<UnicastBusConfig>
<MessageEndpointMappings>
<add Messages="Core" Endpoint="FileWatcherService" />
</MessageEndpointMappings>
</UnicastBusConfig>
In the NSB windows, I see
FileMover: Subscribing to Core.Events.IFileUploadedEvent
FileWatcher: Subscribing FileMoverService#ccc to message type Core.Events.IFileUploadedEvent
The FileMover class implements IHandleMessages, but the code never reaches that because NServiceBus throws the first error.
I tried running Init() in the EndpointConfig, but I still get the same error.
Help me Please! What am I doing wrong?
If you want to move files or other blobs using NServiceBus, look at using our "data bus" capabilities described here:
http://docs.particular.net/NServiceBus/attachments-databus-sample
Turns out you can't Deserialize a FileInfo object. So I'll have to approach the problem completely differently.