Serilog : creating Multiple log files when calling a wcf service - wcf

I have serilog parameters described in web.config as below:
<appSettings>
<add key="serilog:minimum-level" value="Debug" />
<add key="serilog:using:RollingFile" value="Serilog.Sinks.RollingFile" />
<add key="serilog:write-to:File.rollingInterval" value="Day"/>
<add key="serilog:write-to:RollingFile.pathFormat" value="c:\temp\log.txt" />
</appSettings>
In my wcf service, code is as below
public class CalculateService : ICalculateService
{
private Logger _logger;
public CalculateService()
{
_logger = new LoggerConfiguration()
.ReadFrom.AppSettings()
.CreateLogger();
_logger.Debug("calling constructor");
}
}
When I'm calling this service from the Console application, a separate log file is created each time. I want to initialize log only once and want to create a new log file each day.

Related

Is Active Directory authentication used?

I've inherited MVC4 application. It looks like Windows Authentication is used, but I also was told that "Active Directory Authentication" is used for some permissions. I do not see anything in web.config about Active Directory.
In web.config:
<authentication mode="Windows" />
<roleManager defaultProvider="DefaultRoleProvider">
<providers>
<add name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=21bf1234ad634e53" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</roleManager>
In Controller:
[Authorize(Roles = #"ABCD\EFG"), HandleError(ExceptionType = typeof(UnauthorizedAccessException), View = "UnauthorizedUser", Order = 1)]
public class HomeController : Controller
{ .............
}
public ActionResult MyAction()
{
if (!User.IsInRole(#"ABCD\EFG"))
{
// some code
}
//.............
}
Is "Active Directory Authentication" used in this application ?
Thank you
The windows authentication will indeed integrate with Active Directory as long as the application server is on the domain your users are registered in.
The below line in your config file enables such functionality.
<authentication mode="Windows" />
This post might help you get further:
Configure ASP.NET MVC for authentication against AD

Windows-authentication MVC app with Claims, Authenticate called multiple times and looses Security Token cookie

I'm developing Windows-authentication claims-based MVC application. I've implemented the IHttpModule (aka "ClaimsTransformation Module", which interceps the Identity) and custom ClaimsAuthenticationManager (which adds additional claims to this identity), as shown below. Page loads, and I can retrieve newly added claim, but there few serious issues...
The problems are:
Even on initial page load my custom RomesClaimsAuthenticationManager.Authenticate method gets called 27+ times (I assume some calls are parrallel/async).
The FedAuth (SessionToken) cookie check never returns true, even though right after SAM (SessionAuthenticationManager) writes SesstionToken to cookie - I can see it, but at the next call (still during original page load) it's gone - same thing happens if I open other pages.
public class RomesClaimsAuthorizationModule : IHttpModule, IDisposable
{
public void Init(System.Web.HttpApplication application)
{
// intercept PostAuthenticationRequest to add custom logic
application.PostAuthenticateRequest += TransformPrincipal;
}
private static void TransformPrincipal(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
// PROBLEM HERE - this is always false, even after cookie has been set
// check if cookie with auth info about curr user already exists
if (FederatedAuthentication.SessionAuthenticationModule != null &&
FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(HttpContext.Current.Request.Cookies))
{
return;
}
else
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
// this will pick up our custom Romes.Adminn.Security.RomesClaimsAuthenticationManager
// it is specified in web.config, so our app will use it as default
// which will add our custom additional claims to our principal
var transformer = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;
if (transformer != null)
{
var transformedPrincipal = transformer.Authenticate(context.Request.RawUrl, context.User as ClaimsPrincipal);
// generate cookie
SessionSecurityToken sst = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8));
sst.IsReferenceMode = true; // used when there are a lot of claims - will be faster
sst.IsPersistent = true;
// write cookie to session
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sst);
// write to context
context.User = transformedPrincipal;
Thread.CurrentPrincipal = transformedPrincipal;
}
}
}
}
}
Custom ClaimsAuthenticationManager:
public class RomesClaimsAuthenticationManager : ClaimsAuthenticationManager
{
// PROBLEM - THIS GETS HIT 27+ times on original page load
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true)
{
((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Email, "myTestEmail#email.com"));
// i will be making a db call here to get add'l user info from DB, and then convert it into claims
}
return incomingPrincipal;
}
}
Web.config file:
<configSections>
<!--this is required for custom ClaimsAuthorizationManager-->
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<!--this will allow us to write ClaimsPrincipal to a cookie, saving from calls to db on each request-->
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</configSections>
...
<system.identityModel>
<identityConfiguration>
<claimsAuthenticationManager type="ROMES.Admin.Security.RomesClaimsAuthenticationManager, ROMES.Admin" />
</identityConfiguration>
</system.identityModel>
<system.identityModel.services>
<federationConfiguration>
<cookieHandler mode="Default" requireSsl="true" />
</federationConfiguration>
</system.identityModel.services>
<system.web>
<authentication mode="Windows"/>
...
<authorization>
<allow roles="WINDOWS\ROMES_Admins"/>
<deny users="*" />
</authorization>
<!--must be in both here and system.webServer/modules-->
<!--see here WHY: https://msdn.microsoft.com/en-us/library/gg638734.aspx-->
<httpModules>
<add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</httpModules>
</system.web>
<system.webServer>
<!-- same as in system.web/httpModules-->
<modules>
<add name="RomesClaimsAuthorizationModule" type="ROMES.Admin.Security.RomesClaimsAuthorizationModule"/>
<!--this module will handle reading and writing cookie for identity/claims - so that there will be no need to call db every request for user info-->
<add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</modules>
...
</system.webServer>
My main issues are:
(1) why is my Authenticate block gets called so many times and
(2) Why is Session Security Token cookie does not persist - seems like such a waste of resources.
In here
FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(HttpContext.Current.Request.Cookies)
change to
FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(context.Request.Cookie)
and see if the condition started to be true and your code returns.
EDITED after David's comment: context replaced with context.Request.Cookie

WebSecurity.InitializeDatabaseConnection fails with "The Role Manager feature has not been enabled." when called from console program

I have a MVC4 application using SimpleMembership to authenticate users.
I want to add users from a console program.
The console program that references a class library that has the method that will do the user creation.
It looks like this:
public class UserBuilder
{
private static readonly SimpleMembershipInitializer _membershipInitializer;
private static readonly bool _isInitialized;
private static readonly object _initializerLock = new object();
static UserBuilder()
{
LazyInitializer.EnsureInitialized(ref _membershipInitializer, ref _isInitialized, ref _initializerLock);
}
public void HandleEvent(UserAdded #event)
{
if (!WebSecurity.UserExists("ReportModels"))
{
WebSecurity.CreateUserAndAccount("ReportModels", "ReportModels");
};
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
}
}
When I start my console application I get System.Configuration.Provider.ProviderException {"The Role Manager feature has not been enabled."} at the line starting with WebSecurity.InitializeDatabaseConnection.
What do I need to do to accomplish this?
I've tried:
adding the nuget package Microsoft ASP.NET Web Pages 2 Web Data to both the console project and the class library project.
the answers listed in this post: SimpleMembershipProvider not working.
verified the connection string.
verified that the tables are in place in the database.
verified that creating users and authenticating them from the MVC4 project works.
Finally solved it thanks to information found in this blog post: http://insomniacgeek.com/to-call-this-method-the-membership-provider-property-must-be-an-instance-of-extendedmembershipprovider/ and some googling.
In essence I needed to add this to my app.config file:
<system.web>
<profile defaultProvider="SimpleProfileProvider">
<providers>
<add name="SimpleProfileProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"
connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</profile>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
<roleManager defaultProvider="SimpleRoleProvider" enabled="true">
<providers>
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
</providers>
</roleManager>
</system.web>
Please note the enabled="true" on the roleManager element. Without that the same exception will be thrown.

Define a different default ServiceHostFactory foreach workflow

Is it possible to define a standard ServiceHostFactory foreach 'workflow' service (xamlx)
Our customers can make there own workflows (xamlx) using a custom workflow designer. We force the workflowservices into having a WS2007FederationHttpBinding with TransportSecurity. We turn of ServiceMetadataBehavior of for the WorkflowService and finally add a DataContractResolver that does some type resolving.
The ServiceHostFactory
public class MyServiceHostFactory : WorkflowServiceHostFactory
{
protected override WorkflowServiceHost CreateWorkflowServiceHost(
System.ServiceModel.Activities.WorkflowService service,
Uri[] baseAddresses)
{
WorkflowServiceHost host = base.CreateWorkflowServiceHost(service, baseAddresses);
foreach (Uri adres in baseAddresses)
{
if (adres.Scheme == "https")
{
WorkflowCreationEndpoint endpoint = new WorkflowCreationEndpoint(
new WS2007FederationHttpBinding("IWorkflowService_ws2007FederationHttpBinding"),
new EndpointAddress(adres));
host.AddServiceEndpoint(endpoint);
PageflowDataContractResolver.AttachDataContractResolver(endpoint);
}
}
var metadataBehavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
metadataBehavior.HttpGetEnabled = false;
host.WorkflowExtensions.Add(new WorkflowInstanceTracking());
return host;
}
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
return base.CreateServiceHost(constructorString, baseAddresses);
}
protected override WorkflowServiceHost CreateWorkflowServiceHost(System.Activities.Activity activity, Uri[] baseAddresses)
{
return base.CreateWorkflowServiceHost(activity, baseAddresses);
}
}
The workflows exist in a database as Ron Jacob wrote in this blog. 'Consultants' and/or end users can create workflows using a custom tool, but each time they do they must not forget to add a serviceActivation element in the web.config which is not wanted.
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false">
<baseAddressPrefixFilters>
<add prefix="http://localhost" />
</baseAddressPrefixFilters>
<serviceActivations>
<add relativeAddress="~/Workflows/test.xamlx" service="Workflows/test.xamlx" factory="Foo.Bar.MyServiceHostFactory" />
</serviceActivations>
</serviceHostingEnvironment>
<protocolMapping>
<add scheme="https" binding="ws2007FederationHttpBinding" />
</protocolMapping>
..
I think it would be correct to rephrase your question as:
Is there a way to change the default WorkflowServiceHostFactory for a web application so that config-less xamlx activation will use my WSHF instead.
If I have understood your question correctly then I don't think there is a way to do this. I had a quick look to see if there is a place you can override it but couldn't see any. Another way to achieve this is to modify the web.config as necessary when a user uploads a new workflow. Editing the web.config in-flight should result in any currently running pulses of execution being serviced by the existing AppDomain while a new AppDomain is created to service new requests to the web application. Thus no loss of workflow processing should occur. This of course would require some testing and verification.
UPDATE
It looks like this might be possible. If you add the following to your web.config (which is from the default config for workflow activation).
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.xaml.hosting"
type="System.Xaml.Hosting.Configuration.XamlHostingSectionGroup, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="httpHandlers"
type="System.Xaml.Hosting.Configuration.XamlHostingSection, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</sectionGroup>
</configSections>
<system.xaml.hosting>
<httpHandlers>
<add xamlRootElementType="System.ServiceModel.Activities.WorkflowService, System.ServiceModel.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
httpHandlerType="System.ServiceModel.Activities.Activation.ServiceModelActivitiesActivationHandlerAsync, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add xamlRootElementType="System.Activities.Activity, System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
httpHandlerType="System.ServiceModel.Activities.Activation.ServiceModelActivitiesActivationHandlerAsync, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</httpHandlers>
</system.xaml.hosting>
</configuration>
The class ServiceModelActivitiesActivationHandlerAsync that this default config uses is implemented as follows:
internal class ServiceModelActivitiesActivationHandlerAsync : ServiceHttpHandlerFactory, IServiceModelActivationHandler
{
// Methods
public ServiceHostFactoryBase GetFactory()
{
return new WorkflowServiceHostFactory();
}
}
Then instead of using the ServiceModelActivitiesActivationHandlerAsync, provide an implementation yourself which instantiates your own WorkflowServiceHostFactory in the GetFactory method. Update the web.config above to point to your new httpHandlerType and you should be done.
I haven't tested this at all. It's possible IIS will not like the web.config overriding the system.xaml.hosting section.

"No message serializer has been configured" error when starting NServiceBus endpoint

My GenericHost hosted service is failing to start with the following message:
2010-05-07 09:13:47,406 [1] FATAL NServiceBus.Host.Internal.GenericHost [(null)] <(null)> - System.InvalidOperationException: No message serializer has been con
figured.
at NServiceBus.Unicast.Transport.Msmq.MsmqTransport.CheckConfiguration() in d:\BuildAgent-02\work\672d81652eaca4e1\src\impl\unicast\NServiceBus.Unicast.Msmq\
MsmqTransport.cs:line 241
at NServiceBus.Unicast.Transport.Msmq.MsmqTransport.Start() in d:\BuildAgent-02\work\672d81652eaca4e1\src\impl\unicast\NServiceBus.Unicast.Msmq\MsmqTransport
.cs:line 211
at NServiceBus.Unicast.UnicastBus.NServiceBus.IStartableBus.Start(Action startupAction) in d:\BuildAgent-02\work\672d81652eaca4e1\src\unicast\NServiceBus.Uni
cast\UnicastBus.cs:line 694
at NServiceBus.Unicast.UnicastBus.NServiceBus.IStartableBus.Start() in d:\BuildAgent-02\work\672d81652eaca4e1\src\unicast\NServiceBus.Unicast\UnicastBus.cs:l
ine 665
at NServiceBus.Host.Internal.GenericHost.Start() in d:\BuildAgent-02\work\672d81652eaca4e1\src\host\NServiceBus.Host\Internal\GenericHost.cs:line 77
My endpoint configuration looks like:
public class ServiceEndpointConfiguration
: IConfigureThisEndpoint, AsA_Publisher, IWantCustomInitialization
{
public void Init()
{
// build out persistence infrastructure
var sessionFactory = Bootstrapper.InitializePersistence();
// configure NServiceBus infrastructure
var container = Bootstrapper.BuildDependencies(sessionFactory);
// set up logging
log4net.Config.XmlConfigurator.Configure();
Configure.With()
.Log4Net()
.UnityBuilder(container)
.XmlSerializer();
}
}
And my app.config looks like:
<configSections>
<section name="MsmqTransportConfig" type="NServiceBus.Config.MsmqTransportConfig, NServiceBus.Core" />
<section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
<section name="Logging" type="NServiceBus.Config.Logging, NServiceBus.Core" />
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" requirePermission="false" />
</configSections>
<Logging Threshold="DEBUG" />
<MsmqTransportConfig
InputQueue="NServiceBus.ServiceInput"
ErrorQueue="NServiceBus.Errors"
NumberOfWorkerThreads="1"
MaxRetries="2" />
<UnicastBusConfig
DistributorControlAddress=""
DistributorDataAddress=""
ForwardReceivedMessagesTo="NServiceBus.Auditing">
<MessageEndpointMappings>
<!-- publishers don't need to set this for their own message types -->
</MessageEndpointMappings>
</UnicastBusConfig>
<connectionStrings>
<add name="Db" connectionString="Data Source=..." providerName="System.Data.SqlClient" />
</connectionStrings>
<log4net debug="true">
<root>
<level value="INFO"/>
</root>
<logger name="NHibernate">
<level value="ERROR" />
</logger>
</log4net>
This has worked in the past, but seems to be failing when the generic host starts. My endpoint configuration is below, along with the app.config for the service. What is strange is that in my endpoint configuration, I am specifying to use the XmlSerializer for message serialization. I don't see any other errors in the console output preceding the error message. What am I missing?
Thanks, Steve
It looks like this was my own issue, though I had a hard time figuring that out based on the error message that I received. I have a base class for all of my messages:
public abstract class RequestMessage : IMessage {}
Recently, I created a partner message:
public abstract class ResponseMessage<TRequest>
where TRequest : RequestMessage {}
Apparently, when the host was starting up the IStartableBus, it would hit this generic message type and would not handle it correctly. I only really saw the underlying error when running with the DefaultBuilder, rather than the UnityBuilder that I am using in my project. It had something to do with the generic type constraint. I had assumed that this would work, but sadly it did not.
Regards,
Steve