AdminService Init (Prototyp)
This commit is contained in:
1
Host/AdminService.svc
Normal file
1
Host/AdminService.svc
Normal file
@@ -0,0 +1 @@
|
||||
<%@ ServiceHost Language="C#" Debug="true" Service="BeWo.Service.ServiceImplementations.AdminServiceImp" %>
|
||||
@@ -168,6 +168,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="AdminService.svc" />
|
||||
<Content Include="GkvAccountingService.svc" />
|
||||
<Content Include="Admin.aspx" />
|
||||
<Content Include="AnalysisService.svc" />
|
||||
|
||||
@@ -113,25 +113,16 @@
|
||||
<requestLimits maxQueryString="65536" maxUrl="65536" />
|
||||
</requestFiltering>
|
||||
</security>
|
||||
<httpProtocol>
|
||||
<customHeaders>
|
||||
<add name="Access-Control-Allow-Origin" value="*" />
|
||||
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
|
||||
<add name="Access-Control-Allow-Headers" value="Content-Type" />
|
||||
</customHeaders>
|
||||
</httpProtocol>
|
||||
</system.webServer>
|
||||
|
||||
<system.serviceModel>
|
||||
<bindings>
|
||||
<basicHttpBinding>
|
||||
<binding name="TransportSecurity" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
|
||||
<security mode="None">
|
||||
<transport clientCredentialType="None" />
|
||||
</security>
|
||||
<readerQuotas maxStringContentLength="2147483647" />
|
||||
</binding>
|
||||
<binding name="TransportSecurityStreaming" maxBufferSize="65536" maxReceivedMessageSize="2147483647" messageEncoding="Text" transferMode="StreamedRequest">
|
||||
<security mode="None">
|
||||
<transport clientCredentialType="None" />
|
||||
</security>
|
||||
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" />
|
||||
</binding>
|
||||
</basicHttpBinding>
|
||||
</bindings>
|
||||
<system.serviceModel>
|
||||
<services>
|
||||
<service behaviorConfiguration="returnFaults" name="BeWo.Service.ServiceImplementations.EmployeeServiceImp">
|
||||
<endpoint behaviorConfiguration="SecurityAndSessionBehavior" binding="basicHttpBinding" bindingConfiguration="TransportSecurity" name="EmployeeServiceEndpoint" contract="BeWo.Service.ServiceContracts.IEmployeeService" />
|
||||
@@ -184,7 +175,34 @@
|
||||
<service behaviorConfiguration="returnFaults" name="BeWo.Service.ServiceImplementations.EnumTranslationServiceImp">
|
||||
<endpoint behaviorConfiguration="SecurityAndSessionBehavior" binding="basicHttpBinding" bindingConfiguration="TransportSecurity" name="EnumTranslationServiceEndpoint" contract="BeWo.Service.ServiceContracts.IEnumTranslationService" />
|
||||
</service>
|
||||
<service behaviorConfiguration="returnFaults" name="BeWo.Service.ServiceImplementations.AdminServiceImp">
|
||||
<endpoint behaviorConfiguration="webHttpBehaviorConfig" binding="webHttpBinding" bindingConfiguration="webHttpBindingConfig" name="AdminServiceEndpoint" contract="BeWo.Service.ServiceContracts.IAdminService" />
|
||||
</service>
|
||||
</services>
|
||||
<bindings>
|
||||
<basicHttpBinding>
|
||||
<binding name="TransportSecurity" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
|
||||
<security mode="None">
|
||||
<transport clientCredentialType="None" />
|
||||
</security>
|
||||
<readerQuotas maxStringContentLength="2147483647" />
|
||||
</binding>
|
||||
<binding name="TransportSecurityStreaming" maxBufferSize="65536" maxReceivedMessageSize="2147483647" messageEncoding="Text" transferMode="StreamedRequest">
|
||||
<security mode="None">
|
||||
<transport clientCredentialType="None" />
|
||||
</security>
|
||||
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" />
|
||||
</binding>
|
||||
</basicHttpBinding>
|
||||
<webHttpBinding>
|
||||
<binding name="webHttpBindingConfig">
|
||||
<!-- Optional: Maximale Nachrichten- und Puffergröße anpassen -->
|
||||
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
|
||||
<security mode="None" />
|
||||
<!-- Für ungesicherte Verbindungen (HTTP) -->
|
||||
</binding>
|
||||
</webHttpBinding>
|
||||
</bindings>
|
||||
<behaviors>
|
||||
<endpointBehaviors>
|
||||
<behavior name="SecurityBehavior">
|
||||
@@ -197,6 +215,13 @@
|
||||
<HibernateSessionExtension />
|
||||
<SecurityExtension />
|
||||
</behavior>
|
||||
<behavior name="webHttpBehaviorConfig">
|
||||
<!--wichtig: erst Mulittenancy dann session dann security!-->
|
||||
<AdminSecurityExtension />
|
||||
<AdminMultitenancyExtension />
|
||||
<AdminHibernateSessionExtension />
|
||||
<webHttp />
|
||||
</behavior>
|
||||
</endpointBehaviors>
|
||||
<serviceBehaviors>
|
||||
<behavior name="returnFaults">
|
||||
@@ -212,11 +237,15 @@
|
||||
<add name="MultitenancyExtension" type="BeWo.Service.Multitenancy.MultitenancyBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||
<add name="SecurityExtension" type="BeWo.Service.Security.SecurityBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||
<add name="HibernateSessionExtension" type="BeWo.Service.UnitOfWork.HibernateSessionBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||
<add name="AdminMultitenancyExtension" type="BeWo.Service.ServiceBehavior.AdminMultitenancyBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||
<add name="AdminSecurityExtension" type="BeWo.Service.ServiceBehavior.AdminSecurityBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||
<add name="AdminHibernateSessionExtension" type="BeWo.Service.ServiceBehavior.AdminHibernateBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||
</behaviorExtensions>
|
||||
</extensions>
|
||||
</system.serviceModel>
|
||||
<!-- <> <> <> Appsettings <> <> <> -->
|
||||
<appSettings>
|
||||
<add key="AdminServiceIPAddress" value="::1" />
|
||||
<add key="SendMailOnError" value="false" />
|
||||
<add key="SmptServer" value="mail.ownsoft.de" />
|
||||
<add key="SmtpUser" value="bewoplaner.support@ownsoft.de" />
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
<Reference Include="System.ServiceModel">
|
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.ServiceModel.Web" />
|
||||
<Reference Include="System.Text.Encoding.CodePages, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Text.Encoding.CodePages.5.0.0\lib\net461\System.Text.Encoding.CodePages.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -478,8 +479,18 @@
|
||||
<Compile Include="Security\SecurityContextInitializer.cs" />
|
||||
<Compile Include="Security\Right2Methods.cs" />
|
||||
<Compile Include="Security\SecurityUtils.cs" />
|
||||
<Compile Include="ServiceBehavior\AdminHibernateBehavior.cs" />
|
||||
<Compile Include="ServiceBehavior\AdminHibernateBehaviorExtension.cs" />
|
||||
<Compile Include="ServiceBehavior\AdminHibernateContextInitializer.cs" />
|
||||
<Compile Include="ServiceBehavior\AdminMultitenancyBehavior.cs" />
|
||||
<Compile Include="ServiceBehavior\AdminMultitenancyBehaviorExtension.cs" />
|
||||
<Compile Include="ServiceBehavior\AdminMultitenancyContextInitializer.cs" />
|
||||
<Compile Include="ServiceBehavior\AdminSecurityBehavior.cs" />
|
||||
<Compile Include="ServiceBehavior\AdminSecurityBehaviorExtension.cs" />
|
||||
<Compile Include="ServiceBehavior\AdminServiceMessageInspector.cs" />
|
||||
<Compile Include="ServiceContracts\BeWoFault.cs" />
|
||||
<Compile Include="ServiceContracts\IAccountingService.cs" />
|
||||
<Compile Include="ServiceContracts\IAdminService.cs" />
|
||||
<Compile Include="ServiceContracts\IAnalysisService.cs" />
|
||||
<Compile Include="ServiceContracts\IGkvAccountingService.cs" />
|
||||
<Compile Include="ServiceContracts\IMailService.cs" />
|
||||
@@ -492,6 +503,7 @@
|
||||
<Compile Include="ServiceContracts\IStreamingService.cs" />
|
||||
<Compile Include="ServiceContracts\IResourceService.cs" />
|
||||
<Compile Include="ServiceImplementations\AccountingServiceImp.cs" />
|
||||
<Compile Include="ServiceImplementations\AdminServiceImp.cs" />
|
||||
<Compile Include="ServiceImplementations\AnalysisServiceImp.cs" />
|
||||
<Compile Include="ServiceImplementations\GkvAccountingServiceImp.cs" />
|
||||
<Compile Include="ServiceImplementations\MailServiceImp.cs" />
|
||||
|
||||
35
Service/ServiceBehavior/AdminHibernateBehavior.cs
Normal file
35
Service/ServiceBehavior/AdminHibernateBehavior.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using BeWo.Service.UnitOfWork;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.Service.ServiceBehavior
|
||||
{
|
||||
public class AdminHibernateBehavior : IEndpointBehavior
|
||||
{
|
||||
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
|
||||
{
|
||||
foreach (DispatchOperation iOperation in endpointDispatcher.DispatchRuntime.Operations)
|
||||
{
|
||||
iOperation.CallContextInitializers.Add(new AdminHibernateContextInitializer());
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ServiceEndpoint endpoint)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Service/ServiceBehavior/AdminHibernateBehaviorExtension.cs
Normal file
20
Service/ServiceBehavior/AdminHibernateBehaviorExtension.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using BeWo.Service.UnitOfWork;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ServiceModel.Configuration;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.Service.ServiceBehavior
|
||||
{
|
||||
public class AdminHibernateBehaviorExtension : BehaviorExtensionElement
|
||||
{
|
||||
public override Type BehaviorType => typeof(AdminHibernateBehavior);
|
||||
|
||||
protected override object CreateBehavior()
|
||||
{
|
||||
return new AdminHibernateBehavior();
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Service/ServiceBehavior/AdminHibernateContextInitializer.cs
Normal file
25
Service/ServiceBehavior/AdminHibernateContextInitializer.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using BeWo.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.Service.ServiceBehavior
|
||||
{
|
||||
public class AdminHibernateContextInitializer : ICallContextInitializer
|
||||
{
|
||||
public void AfterInvoke(object pCorrelationState)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public object BeforeInvoke(InstanceContext pInstanceContext, IClientChannel pChannel, Message pMessage)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Service/ServiceBehavior/AdminMultitenancyBehavior.cs
Normal file
36
Service/ServiceBehavior/AdminMultitenancyBehavior.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using BeWo.Service.Multitenancy;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.Service.ServiceBehavior
|
||||
{
|
||||
public class AdminMultitenancyBehavior : IEndpointBehavior
|
||||
{
|
||||
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
|
||||
{
|
||||
throw new NotImplementedException("This is a server behavior only");
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
|
||||
{
|
||||
foreach (DispatchOperation iOperation in endpointDispatcher.DispatchRuntime.Operations)
|
||||
{
|
||||
iOperation.CallContextInitializers.Add(new AdminMultitenancyContextInitializer());
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ServiceEndpoint endpoint)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ServiceModel.Configuration;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.Service.ServiceBehavior
|
||||
{
|
||||
public class AdminMultitenancyBehaviorExtension : BehaviorExtensionElement
|
||||
{
|
||||
public override Type BehaviorType => typeof(AdminMultitenancyBehavior);
|
||||
|
||||
protected override object CreateBehavior()
|
||||
{
|
||||
return new AdminMultitenancyBehavior();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using BeWo.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using BeWo.Service.Core;
|
||||
|
||||
namespace BeWo.Service.ServiceBehavior
|
||||
{
|
||||
public class AdminMultitenancyContextInitializer : ICallContextInitializer
|
||||
{
|
||||
public void AfterInvoke(object pCorrelationState)
|
||||
{
|
||||
if (pCorrelationState is MultitenancyOperationContextExt)
|
||||
{
|
||||
OperationContext.Current.Extensions.Remove((MultitenancyOperationContextExt)pCorrelationState);
|
||||
}
|
||||
}
|
||||
|
||||
public object BeforeInvoke(InstanceContext pInstanceContext, IClientChannel pChannel, Message pMessage)
|
||||
{
|
||||
string lTenant = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (pMessage.Properties?.Via is Uri uri)
|
||||
{
|
||||
var query = HttpUtility.ParseQueryString(uri.Query);
|
||||
var tenant = query["tenant"];
|
||||
|
||||
lTenant = tenant;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(lTenant))
|
||||
{
|
||||
var lExt = new MultitenancyOperationContextExt { Tenant = lTenant };
|
||||
OperationContext.Current.Extensions.Add(lExt);
|
||||
return lExt;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw Utils.CreateBeWoFaultException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Service/ServiceBehavior/AdminSecurityBehavior.cs
Normal file
39
Service/ServiceBehavior/AdminSecurityBehavior.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using BeWo.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.Service.ServiceBehavior
|
||||
{
|
||||
public class AdminSecurityBehavior : IEndpointBehavior
|
||||
{
|
||||
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
// Keine zusätzlichen Bindungsparameter erforderlich
|
||||
}
|
||||
|
||||
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
|
||||
{
|
||||
// Verhalten für Clients - hier nicht benötigt
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
|
||||
{
|
||||
// Füge einen Message Inspector hinzu, um eingehende Requests zu überprüfen
|
||||
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new AdminServiceMessageInspector());
|
||||
}
|
||||
|
||||
public void Validate(ServiceEndpoint endpoint)
|
||||
{
|
||||
// Optional: Endpunktvalidierung (falls erforderlich)
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Service/ServiceBehavior/AdminSecurityBehaviorExtension.cs
Normal file
15
Service/ServiceBehavior/AdminSecurityBehaviorExtension.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.ServiceModel.Configuration;
|
||||
|
||||
namespace BeWo.Service.ServiceBehavior
|
||||
{
|
||||
public class AdminSecurityBehaviorExtension : BehaviorExtensionElement
|
||||
{
|
||||
public override Type BehaviorType => typeof(AdminSecurityBehavior);
|
||||
|
||||
protected override object CreateBehavior()
|
||||
{
|
||||
return new AdminSecurityBehavior();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Service/ServiceBehavior/AdminServiceMessageInspector.cs
Normal file
40
Service/ServiceBehavior/AdminServiceMessageInspector.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.ServiceModel;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BeWo.Data;
|
||||
|
||||
namespace BeWo.Service.ServiceBehavior
|
||||
{
|
||||
public class AdminServiceMessageInspector : IDispatchMessageInspector
|
||||
{
|
||||
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
|
||||
{
|
||||
// Hole die erlaubte IP aus den appSettings
|
||||
string allowedIP = ConfigurationManager.AppSettings["AdminServiceIPAddress"];
|
||||
|
||||
// Extrahiere die RemoteEndpoint-IP-Adresse
|
||||
string remoteIP = request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name)
|
||||
? ((RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name]).Address
|
||||
: null;
|
||||
|
||||
// Vergleiche die IPs
|
||||
if (remoteIP == null || !string.Equals(remoteIP, allowedIP, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new UnauthorizedAccessException($"Zugriff verweigert. Remote IP ({remoteIP ?? "Unbekannt"}) ist nicht erlaubt.");
|
||||
}
|
||||
|
||||
return null; // Keine Zustandsinformationen erforderlich
|
||||
}
|
||||
|
||||
public void BeforeSendReply(ref Message reply, object correlationState)
|
||||
{
|
||||
// Keine zusätzliche Logik erforderlich vor dem Senden der Antwort
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Service/ServiceContracts/IAdminService.cs
Normal file
18
Service/ServiceContracts/IAdminService.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.Service.ServiceContracts
|
||||
{
|
||||
[ServiceContract]
|
||||
public interface IAdminService
|
||||
{
|
||||
[OperationContract]
|
||||
[WebGet(UriTemplate = "/Test")]
|
||||
string Test();
|
||||
}
|
||||
}
|
||||
19
Service/ServiceImplementations/AdminServiceImp.cs
Normal file
19
Service/ServiceImplementations/AdminServiceImp.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using BeWo.Service.ServiceContracts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.ServiceModel;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.Service.ServiceImplementations
|
||||
{
|
||||
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
|
||||
public class AdminServiceImp : IAdminService
|
||||
{
|
||||
public string Test()
|
||||
{
|
||||
return "Test erfolgreich!";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user