Adding Operation Behaviors with WCF Facility - wcf

I'm using the WCF Facility for the first time to host a couple
services, both in a console app (for easy debugging) and IIS (for
production). The services use a net.msmq endpoint.
This is how I'm hosting the service in the console app (simplified):
using (var host = new DefaultServiceHostFactory()
.CreateServiceHost(typeof(MyService).AssemblyQualifiedName,
new Uri[0]))
host.Open();
And here's how it's registered:
container.Register(Component.For<UserRequestService>()
.LifestylePerWcfOperation())
What I'd like to do is to add the following behavior to all operations:
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
Here's what I tried:
container.Register(Component.For<IOperationBehavior>()
.UsingFactoryMethod(
x => new OperationBehaviorAttribute
{
TransactionScopeRequired = true,
TransactionAutoComplete = true
}));
But that results in an exception:
System.ArgumentException: The value could not be added to the collection, as the collection already contains an item of the same type: 'System.ServiceModel.OperationBehaviorAttribute'. This collection only supports one instance of each type.
Parameter name: item
at System.Collections.Generic.KeyedByTypeCollection`1.InsertItem(Int32 index, TItem item)
at Castle.Facilities.WcfIntegration.Internal.WcfUtils.AddBehaviors[T](IKernel kernel, WcfExtensionScope scope, KeyedByTypeCollection`1 behaviors, IWcfBurden burden, Predicate`1 predicate)
at Castle.Facilities.WcfIntegration.WcfEndpointExtensions.Install(ServiceEndpoint endpoint, Boolean withContract, IKernel kernel, IWcfBurden burden)
at Castle.Facilities.WcfIntegration.ServiceHostExtensions.Castle.Facilities.WcfIntegration.IWcfExtensionVisitor.VisitEndpointExtension(IWcfEndpointExtension extension)
at Castle.Facilities.WcfIntegration.ServiceHostExtensions.Install(ICollection`1 extensions, IWcfBurden burden)
at Castle.Facilities.WcfIntegration.AbstractServiceHostBuilder.ConfigureServiceHost(ServiceHost serviceHost, IWcfServiceModel serviceModel, ComponentModel model)
at Castle.Facilities.WcfIntegration.AbstractServiceHostBuilder`1.Build(ComponentModel model, Uri[] baseAddresses)
at Castle.Facilities.WcfIntegration.WindsorServiceHostFactory`1.CreateServiceHost(String constructorString, Uri[] baseAddresses)
at Program.Main()
Any ideas?

Related

Cannot create database migration on EF Core but It can when you ask to EnsureCreate database

I am trying to inject some repository to a service and some services to a controller but I am using the DbContext is an assembly that is not the startup project but oddily when i try to call to create a migration it tells me this design is not allowed but if I call the EnsureCreated() method it allows me to create the database... what could be happening
the error
Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create an object of type 'AppDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
---> System.InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions1[Repository.AppDbContext.AppDbContext]' while attempting to activate 'Repository.AppDbContext.AppDbContext'. at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters) at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_4.<FindContextTypes>b__13() --- End of inner exception stack trace --- at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_4.<FindContextTypes>b__13() at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func1 factory)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl
here is the Service DI
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextPool<AppDbContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("ManagementServiceDb"));
});
services.AddIdentity<ApplicationUser, IdentityRole>(options => {
options.SignIn.RequireConfirmedAccount = false;
options.User.RequireUniqueEmail = true;
}).AddEntityFrameworkStores<AppDbContext>();
services.AddScoped<IRepository<Producto>, ProductoRepositorio>();
services.AddScoped<IRepository<RegistroActividad>, RegistroActividadRepositorio>();
services.AddScoped<IRepository<ProductoRegistroActividad>, RegistroActividadesProductoRepositorio>();
services.AddScoped<IRepository<TipoActividad>, TipoActividadRepositorio>();
services.AddScoped<IRepository<ApplicationUser>, UsuarioRepositorio>();
services.AddScoped<UnidadRepositorio>();
services.AddScoped<ProductosServicios>();
services.AddScoped<UsuarioServicio>();
services.AddScoped<UnidadServicios>();
services.AddControllersWithViews();
}
Try to add a parameterless constructor in your DbContext class.
If that doesn't work you might need to add a design time factory as described here.

WCF System.IndexOutOfRangeException in Dispatcher.DispatchOperationRuntime.InspectInputsCore

Issue: Getting below error while WCF service is invoked.
Index was outside the bounds of the array.
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InspectInputsCore(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
System.IndexOutOfRangeException
Need help to resolve this issue.
Details:
We have web-hosted (in same virtual directory, ASP.NET compatiblity enabled, baic http binding) multiple WCF services created as below
6 Services with individual service contracts for each service and respective datacontracts for each operations. Uses custom service host factory which adds a Message Inspector
2 services hosted in below fashion
2 seperate wsdls (design time files, with different schemas) pointing to the same service endpoint implementing the below contract. Uses a different custom service host factory which also adds a Message Inspector
[ServiceContract]
public interface IGenericService
{
[OperationContract(Action = "*", ReplyAction = "*")]
System.ServiceModel.Channels.Message GenericOperation(System.ServiceModel.Channels.Message msgRequest);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ValidateMustUnderstand = false)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class GenericService : IGenericService
{
public Message GenericOperation(Message msgRequest)
{
All of these services are having proxies in SOA platform (Progress Actional). Actional maintains the direct endpoints for invoking the actual service and is able to properly invoke the actual service.
All 8 services are working fine in a server used for UnitTest execution. When deployed to QA servers all 6 services with individual service contracts work fine but the 2 new services (design time wsdls files) thow error listed above.
Code inside MessageInspector (failing services) looks as below. Other Inspector for other set of 6 services is similar.
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
return Stopwatch.StartNew();
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Stopwatch watch = (Stopwatch)correlationState;
watch.Stop();
TimeSpan performanceTime = watch.Elapsed;
watch = null;
// Invoke Performance Logging Code
}
}
ServiceTrace looks as below.
Construct ServiceHost 'XyzServices.SpecificService' (One of the 6 service with individual service contract)
Open ServiceHost 'XyzServices.SpecificService'
All Endpoint listner opened for specific service
Listen at 'specificservice uri'
Processing message 1
Process action 'SpecificService.SpecificOperation.SoapAction'
Execute 'XyzServices.SpecificService.SpecificOperation'
Construct ServiceHost 'XyzServices.GenericService'
Processing message 2
From: Listen at 'XyzServices.SpecificService endpoint'
Activity boundary Start
To: Process action 'GenericService.GenericOperation.SoapAction'
To: Listen at 'XyzServices.SpecificService endpoint'
Activity boundary Stop
Open ServiceHost 'XyzServices.GenericService'
All Endpoint listner opened for Generic service
Process action 'GenericService.GenericOperation.SoapAction'
From: Processing message 2
Activity boundary Start
Received message over channel - Message header looks fine. Does not show message body
ServiceChannel information - Every thing looks fine here for (Unit Test server and QA server)
Handling an exception - shows the exception pasted in question details (only in QA server)
Sent a message over a channel
Aborted InstanceContext
Activity boundary Stop
(This activity looks fine when services run in Unit test server)
I used service trace viewer for the first time, but I noted that 'Processing message 2' activity starts from a activity which is related with the specific service. Does that indicate any problem in the way services are hosted. (where these services need separation)
Please let me know, if more details are needed.
this.InitializeCallContext(ref rpc);
object target = rpc.Instance;
this.DeserializeInputs(ref rpc);
**this.InspectInputs(ref rpc);**
ValidateMustUnderstand(ref rpc);
IAsyncResult result = null;
IDisposable impersonationContext = null;
IPrincipal originalPrincipal = null;
bool isThreadPrincipalSet = false;
try
{
if (this.parent.SecurityImpersonation != null)
{
this.parent.SecurityImpersonation.StartImpersonation(ref rpc, out impersonationContext, out originalPrincipal, out isThreadPrincipalSet);
}
void InspectInputsCore(ref MessageRpc rpc)
{
int offset = this.Parent.ParameterInspectorCorrelationOffset;
for (int i = 0; i < this.ParameterInspectors.Length; i++)
{
IParameterInspector inspector = this.ParameterInspectors[i];
rpc.Correlation[offset + i] = inspector.BeforeCall(this.Name, rpc.InputParameters);
}
}

Performing action before WCF service is shutdown

I have a WCF service hosted in IIS7. The service has a static class with a static list containing strings (sort of log). It periodically write the entries to a file or db.
However when the IIS decides the recyle the app or terminate for whatever reason, the entries in the static field are lost.
Is there any way I can handle the service shuttingdown kind event and persist the data from memory?
Thanks
Shreedhar
I've implemented several services via IIS with a custom service host (originally I did this so I could implement IErrorHandler for global error handling).
You'll need two things - an implementation of ServiceHost and an implementation of ServiceHostFactory, which will call your custom service host. For example (just the relevant parts of code shown):
public class MyCustomServiceHost : ServiceHost
{
protected override void OnClosing()
{
// logic to save off your static data
base.OnClosing();
}
}
public class MyCustomServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyCustomServiceHost(serviceType, baseAddresses);
}
}
In your .svc file, you'd have something like this:
<%# ServiceHost Service="MyCompany.MyServiceName" Factory="MyCompany.MyCustomServiceHostFactory" %>
<%# Assembly Name="MyCustomServiceHost" %>
This is one way to do this (and this dates back to .NET 3.5 days); there are quite likely other ways to accomplish this, but at least this should give you some direction.

Injecting dependencies into MVC3 WCF services using Ninject extensions

I have an MVC3 application which should expose some functions via WCF. Some of these functions have dependencies and I'd like to inject them using Ninject, but I must be missing something obvious here as this does not work. Could anyone give a hint? Here's what I did:
1) in my MVC3 app, I add Ninject Wcf extensions via nuget.
2) I add a .svc file like:
<%# ServiceHost Service="MyWeb.LookupService"
Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"%>
3) I add the corresponding code like (that's just a test so I'm using a dummy interface right here):
[ServiceContract]
public interface ILookupService
{
[OperationContract]
int GetProjectIdByCode(string sCode);
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class LookupService : ILookupService
{
private readonly ISomeRepository _repository;
public LookupService(ISomeRepository repository)
{
_repository = repository;
}
public int GetProjectIdByCode(string sCode)
{
//... use _repository
}
}
4) in App_Start/NinjectMVC3.cs:
private static void RegisterServices(IKernel kernel)
{
string sConnection = ConfigurationManager.ConnectionStrings["SomeEntities"].ConnectionString;
// WCF
kernel.Bind<ServiceHost>().To<NinjectServiceHost>();
kernel.Bind<ISomeRepository>()
.To<AConcreteRepository>()
.WithConstructorArgument("sConnection", sConnection);
}
Now, when I access the svc I get the following exception from Ninject:
System.ArgumentNullException was unhandled by user code
Message=Cannot be null Parameter name: root Source=Ninject
ParamName=root StackTrace:
at Ninject.Infrastructure.Ensure.ArgumentNotNull(Object argument, String name) in
c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Infrastructure\Ensure.cs:line
20
at Ninject.ResolutionExtensions.GetResolutionIterator(IResolutionRoot
root, Type service, Func2 constraint, IEnumerable1 parameters,
Boolean isOptional, Boolean isUnique) in
c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line
258
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters) in
c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line
37
at Ninject.Extensions.Wcf.NinjectServiceHostFactory.CreateServiceHost(Type
serviceType, Uri[] baseAddresses) in
c:\Projects\Ninject\Maintenance2.2\ninject.extensions.wcf\src\Ninject.Extensions.Wcf\NinjectServiceHostFactory.cs:line
48
at System.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(String
constructorString, Uri[] baseAddresses)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.CreateService(String
normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(String
normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String
normalizedVirtualPath)
Can you try to add a protected parameterless constructor to your implementation class.
Guess the servicehost needs a parameterless constructor as well.
I had a look at the Ninject service host factory and from the stack trace provided by you. It looks its failing whne making the following checks:
Ensure.ArgumentNotNull((object) root, "root");
Ensure.ArgumentNotNull((object) service, "service");
Ensure.ArgumentNotNull((object) parameters, "parameters");
Make sure that you are passing all the required parameters when using the NinjectServiceHostFactory. Worth trying to change the order of registration.
Also go through the following link here that explains how to use Ninject to host a wcf service.

Wcf Data Service Service operations

Getting error when I run the wcf data service with the code following the error message:
"The server encountered an error processing the request. See server logs for more details."
Code:
public class WcfDataService1 : DataService<Entities1>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
// TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
// Examples:
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("GetData", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
[WebGet()]
public IQueryable GetData(int Id)
{
if (assayId > 0)
{
var query = from a in this.CurrentDataSource.Entity
where a.ID == Id
select a;
return query;
}
else
throw new DataServiceException(400, "ID is not valid");
}
}
The same code works when I dont return anything from the operation.
UPDATE: The server logs say:
"WebHost failed to process a request.
Sender Information: System.ServiceModel.Activation.HostedHttpRequestAsyncResult/44530215
Exception: System.ServiceModel.ServiceActivationException: The service '/MyWcfDataService.svc' cannot be activated due to an exception during compilation. The exception message is: The type 'MyWcfDataService', provided as the Service attribute value in the ServiceHost directive, or provided in the configuration element system.serviceModel/serviceHostingEnvironment/serviceActivations could not be found.. ---> System.InvalidOperationException: The type 'MyWcfDataService', provided as the Service attribute value in the ServiceHost directive, or provided in the configuration element system.serviceModel/serviceHostingEnvironment/serviceActivations could not be found.
at System.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(String constructorString, Uri[] baseAddresses)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.CreateService(String normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(String normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath)
--- End of inner exception stack trace ---
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result)
Process Name: WebDev.WebServer40
Process ID: 1124
For more information, see Help and Support Center at
Can anyone please help me with the solution.
Also, if I want to expose my own entity and not the one created by EF, how to go about doing that.. any ideas??
Just modified the return type to
IQueryable<Entity> and it worked.