How to use DefaultModelBindingMessageProvider in ModelBinders - custom-model-binder

We have a custom DateTimeModelBinder that used to work fine with ASP.NET Core 1.1, but after upgrading to 2.2, it fails. This is the breaking part:
bindingContext.ModelState.TryAddModelError(
bindingContext.ModelName,
bindingContext.ModelMetadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor(
valueProviderResult.ToString()));
The error is:
Method not found: 'Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IModelBindingMessageProvider Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata.get_ModelBindingMessageProvider()'.
The failing part is:
bindingContext.ModelMetadata.ModelBindingMessageProvider
Obviously something has changed. I found this message explaining a bit about this breaking change, but all of it:
https://github.com/aspnet/Announcements/issues/240
Apparently we have to use DefaultModelBindingMessageProvider now, but how does the whole application share a common one, inluding model binders?
Problem is, in ModelBinders, the bindingContext.ModelMetadata.ModelBindingMessageProvider used to poing at a class containing the strings, but now is pointing to the abstract class and hence fails with the above error.
Using this instead works, but newing up this class for each use seems wrong (also, changes to the translations would not be reflected).
bindingContext.ModelState.TryAddModelError(
bindingContext.ModelName,
new DefaultModelBindingMessageProvider().ValueMustNotBeNullAccessor(
valueProviderResult.ToString()));
I feel I should be able to set the ModelBindingMessageProvider property of the ModelMetadata in the bindingContext in my Startup.cs, but haven't found out how (or if I am on the right track). Am I?

It actually does work as the first code snippet shows. My problem was that the code shown was in a nuget package that depended on Microsoft.AspNetCore.Mvc version 1.1.3. In the project where I used the nuget package, I had simply overridden Microsoft.AspNetCore.Mvc to version 2.2.0 and assumed this was good enough (code was the same for both implementations).
But I assumed wrong: The code is identical, but the ModelBindingMessageProvider was changed to an abstract class/object (from a normal class/object) and using the compiled nuget package for 1.1.3 hence continued to point at the wrong type that was not/could not be updated by the 2.2.0 aspnetcore. Upgrading the dependency in nuget package to 2.2.0 made the nuget package work just fine.

Related

Is there a fix for InheritanceManager breaking static type checking?

I have added django-model-utils to an existing (large) project, and the build is now failing, as part of the build includes static type checking with mypy.
It complains that models that I have added objects = InheritanceManager() to, don't have attributes for reverse ForeignKeys, if the reverse FK is accessed in a method on that model. For example, take the following:
class Student(Model):
school = ForeignKey(School, related_name='students')
class School(Model):
objects = InheritanceManager() # IRL School is a subclass of some other model
def something(self):
return self.students.filter(...)
Then running mypy on it, will return:
error: "School" has no attribute "students"
And even if I remove the related_name, and use self.student_set (i.e. the default django relation), it will still produce the same type of error. Only removing the InheritanceManager fixes the static type checking. Of course, I'm using it for a reason as I need to select_subclasses elsewhere in the code.
Has anyone come across this, or have a fix?
django-stubs uses plugin to add all managers. This plugin is triggered only if added manager is a "subclass" (not just real subclass, but also recognizable by mypy as such) of models.Manager.
django-model-utils is untyped, so InheritanceManager is in fact Any for mypy, and plugin does not see it. To solve exactly this issue I was adding py.typed marker to django-model-utils as a CI stage after package installation. You can also use a fork with py.typed or create a stub package for django-model-utils. This can result in other issues and doesn't give good type checking (all unannotated methods have Any as implicit arguments and return type), but is better than nothing. For my needs the marker was sufficient.
py.typed marker is an empty file located in package root (venv/lib/.../django_model_utils/py.typed) - it tells mypy that package does not need separate stubs and contains all necessary types.

Spring project package problem that needs to be addressed

I have tried my every possible ways of adding class in different packages such as application class in package com.packagename and my controller in different package named model and when i try to execute the program it returns the default white label error and when i put the classes in the same package it runs successfully.
So i wanted to ask if there is any problem with the project or i need to give any path.
Before I have also tried notations that says component scan and all but that to did not came handy
Let's say your main class(which is annotated with #SpringBootApplication) is in the package "com.somepackage", then try putting your controller in "com.somepackage.controller"(It is recommended that other classes are placed in the subpackage of your main class). with this change it should work.
You put your classes in wrong places and your package are very messy. You should have a structure like this
--src
main
java
com.boltforever.moviecatalog
model
service
MyService.java
controller
MyController.java
MovieCatalogServiceApplication.java
And this should work

ASP.net Core Entity Framework CurrentValues.SetValues() best current alternative

As those of you working with Entity Framework Core may know, the current version does not have an implementation for CurrentValues.SetValues() for Entities. It looks like support for this will come in the next release v1.1 as this issue states. Until then, does anybody have a solution that works for updating entity entries?
For context, the SetValues function in the past entity framework takes an entity and updates it properties to the values of an entity passed as a parameter i.e.:
var updatedEntity = currentEntity.CurrentValues.SetValues(newValues);
_dbContext.SaveChanges();
I've found some implementations using PropertyInfo to make a generic update function but haven't found anything that looks to be a nice clean solution. Might just have to take what I can get though :)
p.s. I realize this function only worked for simple entities that don't have complex object graphs that would require updating other related entities. My use case is simple. It's just annoying to have to manually map properties right now.
EDIT: Now that EF Core v1.1.0 has been released, CurrentValues.SetValues() will work.
See the following code snippet
var currentEntity = dbSetEntity.Find(id);
_dbContext.Entry(currentEntity).CurrentValues.SetValues(newValues);

Xamarin Forms Labs - Geolocator

How do you use the "GeoLocator" function in Xamarin Forms Labs. When i added the "GeoLocator" method in my class i kept getting the error that this.SetProperty does not exist. Anyone know how to use "GeoLocator"?
SetProperty is only available on the very latest pre release nuget package, and it's a method from our Base ViewModel...
You have to show your code to see what you are trying to do.
but it should be as simple as this:
var geolocator = DependencyService.Get<IGeolocator>();
var result = geolocator.GetPositionAsync(10000);
var strLatitude = result.Latitude.ToString("N4");
var strLongitude = result.Longitude.ToString("N4"),
In addition to Rui's answer, I would recommend using Plugins for Xamarin for this type of behavior. Specifically, the Geolocator Plugin for Xamarin and Windows.
Both of these geolocation codebases derived from Xamarin.Mobile, but as far as I can tell, the plugin is a bit more up-to-date, and supports Windows 10 (UWP) development as well.
If you post some of the code that you are using, it will be easier to help you out. But in the meantime, SetProperty does not exist because you are not inheriting from the Xamarin.Forms.Labs.Data.ObservableObject class. It contains the SetProperty method which is merely an implementation of INotifyPropertyChanged (changes the property if the value is different and raises the PropertyChanged event).
So you can either inherit from the XFormsLab's ObservableObject (or it's base view model class which inherits from ObservableObject, Xamarin.Forms.Labs.Mvvm.ViewModel) and then you will have access to SetProperty. Or you can not use SetProperty at all and use your own implementation of INotifyPropertyChanged
We took the code from this library and cleaned it up. You can clone the repo here:
https://github.com/MelbourneDeveloper/Adapt.Presentation.git
It is complete with samples for each platform. If you run the sample, you will see a tab for GeoLocator and it should run on all platforms. Android and UWP have been tested thoroughly.
The NuGet package Adapt.Presentation works to some extent but I've had difficulty getting it to work correctly on all platforms.

Functionality change while upgrading to Castle Windsor 3.3.0 from 3.2.0

I am attempting to migrate from version 3.2.0 to 3.3.0. I am getting a compile error. I could not find an entry in the "Breaking Changes" section but here are my two errors in hope someone can guide me to a workable alternative.
public void RegisterTypeSingleton<T>(Type component, string name)
{
if (_container.Kernel.HasComponent(name))
_container.Kernel.RemoveComponent(name);
_container.Register(Component.For<T>().ImplementedBy(component).Named(name).LifeStyle.Singleton);
}
It seems Kernel.RemoveComponent() function has been depreciated. What has replaced this?
The second compiler error is at _container.Register(Component.For<T>().ImplementedBy(component).Named(name).LifeStyle.Singleton);
I am getting "The Type 'TService' must be a reference type in order to use it as a parameter.
I think you might be upgrading from an older version than 3.2.0. See below.
The removal of IKernel.RemoveComponent() is documented in the Breaking Changes document with v3.0.0. Here is the extract where Krzysztof explains why it was removed:
change - Removed the following methods:
GraphNode.RemoveDepender,
GraphNode.RemoveDependent,
IKernel.RemoveComponent,
IKernelEvents.ComponentUnregistered,
INamingSubSystem.this[Type service],
INamingSubSystem.GetHandler,
INamingSubSystem.GetService2Handler,
INamingSubSystem.GetKey2Handler,
INamingSubSystem.UnRegister(String key),
INamingSubSystem.UnRegister(Type service)
Also INamingSubSystem.Register now takes only IHandler as its argument
impact - low
fixability - none
description - The methods were implementation of "remove component from the container" feature
which was flawed and problematic, hecen was scraped.
fix - Working around is quite dependant on your specific usage. Try utilizing IHandlerSelectors.
For changed Register method, just update your calling code not to pass the name.
handler.ComponentModel.Name is now used as the key, as it was happening in all places so far
anyway, so this change should have no real impact.
RegisterComponent() won't overwrite an existing service registration, it'll just register another component for the same service, unless you specify the same name where it'll throw an exception informing you there is another component registered with that name. If your application doesn't replace components very often you could use the IsDefault() method on the registration to get Windsor to resolve the new component by default, just note the other component is still registered.
If your application replaces components often and you don't want the other registrations left there, you'd be best using a custom IHandlerSelector or ISubDependencyResolver so Windsor will ask you each time what component you want used for a specific service.
Also in v3.0.0 a change was made to ensure that value types cannot be passed to the registration methods. You'll need to add a generic constraint to your method that accepts a generic parameter so that it also only accepts reference types:
public void RegisterTypeSingleton<T>(Type component, string name)
where T : class
{
...
}

Resources