We have automapper v4.2 which mostly works fine, however every 4-6 weeks we get this weird error when the mapping stops
Mapping types:
DynamicContentSearchResultItem -> Full
Models.Messages.Search.DynamicContentSearchResultItem -> Models.Alerts.Views.Client.Full
Destination path:
List`1[0]
It doesn't even complain about any specific property, just plainly stops working unless we reset the app pool.
All the mappings are registered and initialized on Application_Start like
Mapper.CreateMap<DynamicContentSearchResultItem, ClientFull>()
.IncludeBase<DynamicContentSearchResultItem, ClientTraveller>()
.ForMember(d => d.Assessment, AssessmentTransformer)
.ForMember(d => d.ManagerAdvice, ManagerAdviceTransformer);
and its invoked in the code when the mapping's about to be called after search as
var alerts = Mapper.Map<List<InternalFull>>(results, optionsParam).ToList<IArticle>();
I would appreciate all help.
thanks
Related
builder.Services.AddDbContext<AppDbContext>(x =>
{
x.UseSqlServer(builder.Configuration.GetConnectionString("SqlConnection"), option =>
{
option.MigrationsAssembly(Assembly.GetAssembly(typeof(AppDbContext)).GetName().Name);
});
});
System.InvalidOperationException: 'Cannot modify ServiceCollection after application is built.'
When I run the program I get the above error.
However, when trying to migrate, I get the following error
Unable to create an object of type 'AppDbContext'.
It looks like your adding this after builder.Build() has been called, difficult to see without the full code.
Can you try moving it before?
I updated my ReactiveUI.Validation package from version 1.5 and now it's <package id="ReactiveUI.Validation" version="2.1.1" targetFramework="net472" />. But after this I encountered the following:
I needed to replace all generic ReactiveValidationObject<InputParamViewModel> with ReactiveValidationObject. Overwise, it's underlined like error. OK, fine. I did it.
And all the next errors are related to ValidationRule methods and if in the previous version this :
var intervalIsValid = this
.WhenAnyValue(x => x.From.Value, x => x.To.Value, x => x.ForceValidation,
(from, to, forceValidation) => new Interval<decimal?> {From = From.Value, To = To.Value}).Select(x =>
(!ForceValidation && (x.From == null && x.To == null)) || x.IntervalIsValid(IsMandatory));
this.ValidationRule(_ => intervalIsValid, (vm, state) => !state ? Validation.IncorrectValue : string.Empty);
works perfectly, in the new version it's unacceptable due to the wrong params in ValidationRule method (Cannot resolve method ValidationRule(lambda expression, lambda expression)).
I tried to replace that ValidationRule with this:
var observableValue = this
.WhenAnyValue(x => x.From.Value, x => x.To.Value, x => x.ForceValidation,
(from, to, forceValidation) => new Interval<decimal?> { From = From.Value, To = To.Value });
this.ValidationRule(observableValue, x => (!ForceValidation && (x.From == null && x.To == null)) || (x.IntervalIsValid(IsMandatory)), state => Validation.IncorrectValue);
according to documentation (https://www.reactiveui.net/api/reactiveui.validation.extensions/validatableviewmodelextensions/83edc663).
Now there are no errors and the app compiles but this validation doesn't work. The fields are accepted all the time even though I leave them empty. I receive no error message from my app and it continues working.
If you are using ReactiveValidationObject, then I'd suppose that ReactiveUI.Validation integrates with the UI framework that relies on the INotifyDataErrorInfo implementation, and no BindValidation extension method is involved. In this case, according to the ReactiveValidationObject implementation, providing the names for the validated properties might help. Let's consider the following code snippet as an example:
IObservable<bool> passwordsObservable =
this.WhenAnyValue(
x => x.Password,
x => x.ConfirmPassword,
(password, confirmation) => password == confirmation);
this.ValidationRule(
vm => vm.ConfirmPassword, // The property name selector expression.
passwordsObservable, // IObservable<bool>
"Passwords must match."); // Validation error text.
The code snippet above tells ReactiveUI.Validation that a new validation rule should be created from an object of type IObservable<bool> that indicates the validity of a property, and the associated property name is determined based on the provided selector expression (e.g. from vm => vm.ConfirmPassword we get the ConfirmPassword property name).
If that validation rule wasn't associated with a property (e.g. if we didn't pass a property name), then the library wouldn't be able to figure out which validation rules are associated with a validated property. So a rule of thumb when working with INotifyDataErrorInfo and regular WPF or Avalonia bindings is to always specify the property name.
If the issue persists or you get stuck in resolving this, feel free to file a new issue in the ReactiveUI.Validation repository with a repro project, this way we'll be able to look through the codebase and help out with fixing this!
Worth noting, that we have evergreen sample apps targeting Avalonia, WPF, Xamarin Forms etc. in the ReactiveUI.Validation core repository https://github.com/reactiveui/ReactiveUI.Validation/blob/d5089c933e046c5ee4a13149491593045cda161a/samples/LoginApp/ViewModels/SignUpViewModel.cs#L43 So if you'd like to familiarize yourself with the updated ValidationRule APIs, feel free to browse and debug the LoginApp.*.sln sample solutions (LoginApp.Wpf.sln should be relevant according to the hashtags).
I have a MassTransit routing slip configured and working. For reference, the routing slip takes in an ID of an item in a MongoDB database and then creates a "version" of that document in a SQL database using EF Core. The activities (as commands) are:
Migrate document to SQL
Update audit info in MongoDB document
Update MongoDB document status (i.e. to published)
All of the above are write commands.
I have added a new 1st step which runs a query to make sure the MongoDB document is valid (e.g. name and description fields are completed) before running the migration. If this step fails it throws a custom exception, which in turns fires a failed event which is then picked up and managed by my saga. Below is a snippet of my activity code followed by the routing slip builder code:
Activity code
var result = await _queryDispatcher.ExecuteAsync<SelectModuleValidationResultById, ModuleValidationResult>(query).ConfigureAwait(false);
if (!result.ModuleValidationMessages.Any())
{
return context.Completed();
}
return context.Faulted(new ModuleNotValidException
{
ModuleId = messageCommand.ModuleId,
ModuleValidationMessages = result.ModuleValidationMessages
});
Routing slip builder code
builder.AddActivity(
nameof(Step1ValidateModule),
context.GetDestinationAddress(ActivityHelper.BuildQueueName<Step1ValidateModule>(ActivityQueueType.Execute)),
new SelectModuleValidationResultById(
context.Message.ModuleId,
context.Message.UserId,
context.Message.LanguageId)
);
builder.AddSubscription(
context.SourceAddress,
RoutingSlipEvents.ActivityFaulted,
RoutingSlipEventContents.All,
nameof(Step1ValidateModule),
x => x.Send<IModuleValidationFailed>(new
{
context.Message.ModuleId,
context.Message.LanguageId,
context.Message.UserId,
context.Message.DeploymentId,
}));
Whilst all of this works and the event gets picked up by my saga I would ideally like to add the ModuleValidationMessages (i.e. any failed validation messages) to the event being returned but I can't figure out how or even if that's possible (or more fundamentally if it's right thing to do).
It's worth noting that this is a last resort check and that the validation is checked by the client before even trying the migration so worse case scenario I can just leave it has "Has validation issues" but ideally I would like to include the derail in the failed response.
Good use case, and yes, it's possible to add the details you need to the built-in routing slip events. Instead of throwing an exception, you can Terminate the routing slip, and include variables - such as an array of messages, which are added to the RoutingSlipTerminated event that will be published.
This way, it isn't a fault but more of a business decision to terminate the routing slip prematurely. It's a contextual difference, which is why it allows variables to be specified (versus Faulted, which is a full-tilt exception).
You can then pull the array from the variables and use those in your saga or consumer.
I've been trying to add an EventLog Provider for logging in my ASP.NET Application. I was able to add it to the 'Application' source, but there's a lot of information in that log and I'd like for it to be under it's own source. I've actually gotten 3 logs to be written to it's own source, but I have no idea how or why. This is what my code looks like right now:
CreateWebHostBuilder(args)
.ConfigureLogging( logging =>
{
logging.AddEventLog(
new Microsoft.Extensions.Logging.EventLog.EventLogSettings
{
SourceName = "MySweetApp",
MachineName = ".",
LogName = "MySweetApp",
Filter = (category, level) =>
{
if (category.EndsWith("Controller") || level >= LogLevel.Error)
{
return true;
}
return false;
},
});
})
.Build()
.Run();
I've already added a registry key there for this app (since the app doesn't have admin rights and can't add a source) along with the EventMessageFile of C:\Windows\Microsoft.NET\Framework64\v4.0.30319\EventLogMessages.dll. I've messed with different values of this including the non-64 framework folder and other v2 versions. There are no errors or warnings, and I can't find any logs that have anything related in them. I've also added a debug logger with .AddDebug() and it prints just fine the debug window.
I'm guessing it's something on the server side of things and not my code. Thanks in advance.
UPDATE: I can now re-create my app creating error logs in the eventlog. If I start my program by double-clicking the .exe, there is an authentication error that is thrown and gets sent to the log.
Found it. I still had a "Logging" section of my appsettings.json that was set default to warning. Deleted that section and everything started printing!
I have a fully working MassTransit saga, which runs some commands and then executes a request/response call to query a database and then ultimately return a response to the calling controller.
Locally this all works now 99% of the time (thanks to a lot of support I've received on here). However, when deployed to my Azure VM, which has a local copy of RabbitMQ and the 2 ASP.NET Core services running on it, the first call to the saga goes through straight away but all subsequent calls timeout.
I feel like it might be related to the fact that I'm using an InMemorySagaRepository (which in theory should be fine for my use case).
The saga is configured initially like so:
InstanceState(s => s.CurrentState);
Event(() => RequestLinkEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => LinkCreatedEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => CreateLinkGroupFailedEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => CreateLinkFailedEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => RequestLinkFailedEvent, x => x.CorrelateById(context => context.Message.LinkId));
Request(() => LinkRequest, x => x.UrlRequestId, cfg =>
{
cfg.ServiceAddress = new Uri($"{hostAddress}/{nameof(SelectUrlByPublicId)}");
cfg.SchedulingServiceAddress = new Uri($"{hostAddress}/{nameof(SelectUrlByPublicId)}");
cfg.Timeout = TimeSpan.FromSeconds(30);
});
It's worth noting that my LinkId is ALWAYS a unique Guid as it is created in the controller before the message is sent.
ALSO when I restart the apppool it works again for the first call and then starts timing out again.
I feel like something might be locking somewhere but I can't reproduce it locally!
So I wanted to post my solution to my own problem here in the hopes that it will aide others in the future.
I made 3 fundamental changes which either in isolation or combination solved this issue and everything now flys and works 100% of the time whether I use an InMemorySagaRepository, Redis or MongoDB.
Issue 1
As detailed in another question I posted here:
MassTransit saga with Redis persistence gives Method Accpet does not have an implementation exception
In my SagaStateMachineInstance class I had mistakenly declared the CurrentState property as a 'State' type when it should have been a string as such:
public string CurrentState { get; set;}
This was a fundamental issue and it came to light as soon as I started trying to add persistence so it may have been causing troubles when using the InMemorySagaRepository too.
Issue 2
In hindsight I suspect this was probably my main issue and I'm not completely convinced I've solved it in the best way but I'm happy with how things are.
I made sure my final event is managed in all states. I think what was happening was my request/response was finishing before the CurrentState of the saga had been updated. I realised this was happening by experimenting with using MongoDB as my persistence and seeing that I had sagas not completing stuck in the penultimate state.
Issue 3
This should be unnecessary but I wanted to add it as something to consider/try for those having issues.
I removed the request/response step from my saga and replaced it with a publish/subscribe. To do this I published an event to my consumer which when complete publishes an event with the CorrelationId (as suggested by #alexey-zimarev in my other issue). So in my consumer that does the query (i.e. reuqest) I do the following after it completes:
context.Publish(new LinkCreatedEvent { ... , CorrelationId = context.Message.CorrelationId })
Because the CorrelationId is in there my saga picks it up and handles the event as such:
When(LinkCreatedEvent )
.ThenAsync(HandleLinkCreatedEventAsync)
.TransitionTo(LinkCreated)
I'm really happy with how it all works now and feel confident about putting the solution live.