Hi,
I'm trying to upgrade the NuGet packages for one of our appstore applications from 9.2 to 10.2, and need to figure out how the new Dependency Injection code works. Our webapplication is hosted in Azure and runs on .NET Framework 4.8.
According to https://community.superoffice.com/no/technical/forums/general-forums/announcements/breaking-netserver-core-changes/ it seems like code somewhat like this should work. Here I'm using the HttpContextProvider (which is found in the NuGet package SuperOffice.CRM.Web, which apparently is tagged with "This is for onsite integrations only"). I've tried using the ThreadContextProvider as well, with same result.
var services = new ServiceCollection();
services
.AddNetServerCore<SuperOffice.Web.Security.HttpContextProvider>()
.AddSoDatabase()
.AddServicesProxies()
//.AddSingleton<ILogger, SuperOffice.Logging.SoLogger>()
.AddSingleton<IContextInitializer, ContextInitializerForHTTP>()
;
var provider = services.BuildServiceProvider(true);
provider.RegisterWithNetServer();
var SoSession = SuperOffice.SoSession.Authenticate("username", "password");
var name = SuperOffice.SoSystemInfo.GetCurrent().CompanyName;
In my ContextInitializerForHTTP I've made a rudimentary attempt at telling it where the webservices are.
internal class ContextInitializerForHTTP : IContextInitializer
{
public void InitializeContext(string contextIdentifier)
{
ConfigFile.WebServices.RemoteBaseURL = "https://demo.geaslabs.no/SuperOffice/Remote/";
ConfigFile.Services.RemoteBaseURL = "https://demo.geaslabs.no/SuperOffice/Remote/";
ConfigFile.Services.ApplicationToken = "????";
}
}
When running this code I'm getting and error complaining about not being able to connect to SQL server (which it shouldn't, it should talk to webservices)
I was under the impression that adding .AddServicesProxies() was required to switch from "local" mode to "remote" mode.
Has anyone gotten this to work?
All Replies (8)
Hi Frode,
Sorry for the trouble. If you are connecting in local mode, just use UseOnPremAD and AddServicesImplementation.Should not need proxies.
var services = new ServiceCollection();
services
.AddNetServerCore<ProcessContextProvider>(
options =>
{
options.UseOnPremAD();
}) //10.2.1
.AddSoDatabase()
.AddServicesImplementation();
var provider = services.BuildServiceProvider(true);
provider.RegisterWithNetServer();
var resolvers = PluginFactory.Create<ISoIdentityResolver>();
using (SoSession.Authenticate("USER", "PASSWORD"))
{
var c = ContactRow.GetFromIdxContactId(2);
Console.WriteLine("Loaded {0}...", c.Name);
}
Hope this helps.
Hi Tony, thanks for replying.
Unfortunately I can't get this working either. Note, this is in a project where I've used the SuperOffice.DevNet.Online.Login project as the base for getting authentication to work in our multi-tentant Azure hosted app-store application.
Instead of ProcessContextProvider, I'm assuming I need some variant that works in an HTTP environment.
And I'm not sure why UseOnPremAD would be right, since it's neither OnPrem or Active Directory (I'm assuming that's the AD part).
In my initial post I'm referring to a locally installed SuperOffice, but my ultimate goal is to get it working against online.superoffice.com.
Also, does the PluginFactory.Create call have any practical effect?
Sorry for barrage of questions.
Hi Frode,
When your OP mentions "a locally installed SuperOffice", then my response makes sense, at least to me. Now it seems the OP has changed and you state "one of our appstore applications", etc etc... Impossible to assume what people want one thing yet mean something else entirely. As far as I see this topic is all over the place.
In reference to the comment:
"HttpContextProvider (which is found in the NuGet package SuperOffice.CRM.Web, which apparently is tagged with "This is for onsite integrations only")"
That is because that project is only for onsite UI changes that use PageBuilder.
If you are using the context initializer and context resolver classes in the SuperOffice.DevNet.Online.Login library, then you should probably be using the PartnerHttpContextProvider and not the HttpContextProvider, which is in SuperOffice.DevNet.Online.Login. You actually contributed to this library, so I don't understand your misunderstanding.
Yes, for remove mode, use the ServicesProxies.
.AddNetServerCore<SuperOffice.DevNet.Online.Login.PartnerHttpContextProvider>()
.AddServicesProxies()
// Without this, because if the ContextInitializerPlugin in the library, the SuperOffice.DevNet.Online.Login.ContextInitializer should still be called automatically.
// If not you can try this, but it should not be necessary.
//.AddSingleton<IContextInitializer, SuperOffice.DevNet.Online.Login.ContextInitializer>()
I do apologize for all of these changes. It's a real PITA this stuff happens in the middle Major versions without notice, and all I can do it say I am sorry.
Hi Tony, yes, sorry about the confusing topic. The end goal is to get the appstore application working, but during the struggles I shifted focus to "let's try to get it working locally first".
I've redeployed the app to Azure using the suggested code, and I'm testing it against SOD.
The issue now is that the Authentication method fails with the error "IServiceProvider is not registered with NetServer", which was the original issue I had before starting to dig into this confusing rabbithole that I've dragged you into.
Basically, the only difference I've made between the old version of my code ( which used Nuget v9.2) and now is that I've added this section just before I call the SoSession.Authenticate method.
var services = new ServiceCollection();
services
.AddNetServerCore<SuperOffice.DevNet.Online.Login.HttpContextProvider>()
.AddServicesProxies();
var provider = services.BuildServiceProvider(true);
provider.RegisterWithNetServer();
SoSession session = SoSession.Authenticate(new SoCredentials() { Ticket = context.Ticket });
In the ContextResolver.cs I've removed the attribute (because it seems like it doesn't exist anymore)
[ContextResolverPlugin("OnlineTenantContextResolver", -1)]
and In ContextInitializer.cs I've removed the attribute
[ContextInitializerPlugin("OnlineTenantContextInitializer")]
and lastly in HttpContextProvider.cs I've removed the attribute
[SoContextProviderAttribute( "PartnerHttpContext" )]
Should those attributes still be used? And if so, where have they been moved to?
Hi Frode,
You right, unbeknownst to me that was removed that in 10.2.1. There has been a lot of changes around user identity and principal, with zero documentation or guidance provided, and the only communication I have received is that there are more changes coming.
My advice is to spend whatever time on trying to get this working instead on porting what you have to use the SuperOffice.WebApi libraries instead - it's likely to be a lot less work.
Ok, thanks, Tony!
Then I think I'll port our application over to .NET 7, and switch over to use the SuperOffice.WebApi instead.
Hi Everyone, we've run into this exact same issue as well. So is there any news on how to use the latest NetServer versions in remote mode for a multi-tenant online application?
Moving to webapi is a very unacceptable solution on the short term in our case. I don't see any good reason for this scenario not to work anymore, that would mean there is also no good reason for this package to exist any longer and being updated with breaking changes imho..
We've spend quite some time on trying to figure this out, but for now we see 2 possibilities:
- It's a bug, which is kind of weird as just the very first scenraio of session.authenticate call fails.
- We really miss some essential documentation on how to use the new package in remote mode? After a lot of trying we did get some messages like "Database not configured", pointing in the direction of it trying to connect locally instead of remote.
Any clarification is welcome, thanks!
After some debugging with the help of Jens we managed to get the WCF proxies to work again! Thank you.
After the 10.2 changes 3 things needed to be done in our case:
- Prepare the service collection:
var services = new ServiceCollection();
services
.AddNetServerCore<HttpContextProvider>()
.AddServicesProxies();
var provider = services.BuildServiceProvider(true);
provider.RegisterWithNetServer();
- Use a suitable ContextProvider, build-in or in our case a custom HttpContextProvider. As I understood this might change in future with more build-in functionality.
- Then the missing piece, the current versions have trouble in resolving the SoRemoteWcfPrincipal (will be fixed in future), include the below code somewhere at your service collection registration to make it work:
[ClassFactory(typeof(SoPrincipal), FactoryPriority = FactoryPriority.High)]
public class SoRemoteWcfPrincipalFactory : IPrivateFactory
{
public SoRemoteWcfPrincipalFactory() { }
object IPrivateFactory.Create(Type type, Type[] constructorArgumentTypes, object[] constructorArguments)
{
if (constructorArguments.Length == 1)
{
if (constructorArguments[0] is IEnumerable<ClaimsIdentity> identities && identities.Any())
{
return CreateSoRemoteWcfPrincipal(identities);
}
if (constructorArguments[0] is ClaimsIdentity identity)
{
return CreateSoRemoteWcfPrincipal(new[] { identity });
}
}
return null;
}
SoRemoteWcfPrincipal CreateSoRemoteWcfPrincipal(IEnumerable<ClaimsIdentity> identities)
{
var constructor = typeof(SoRemoteWcfPrincipal).GetConstructors(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).First();
return constructor.Invoke(new object[] { identities }) as SoRemoteWcfPrincipal;
}
}