Custom Configuration Class with KeyValue pairs inside - c#

I want to implement the following configuration section:
<Services>
<Service name="Service-1" provider="Provider-1" type="Type-1">
<add key="Region" value="region-name-1"/>
<add key="AccessKey" value="1234567890"/>
<add key="SecretKey" value="asdfghhkl"/>
</Service>
<Service name="Service-2" provider="Provider-1" type="Type-2">
<add key="Region" value="region-name-2"/>
<add key="EndpointName" value="tyudfv.endpoint.com"/>
<add key="AccessKey" value="1234567890"/>
<add key="SecretKey" value="asdfghhkl"/>
</Service>
</Services>
And I'm struggling with two issues:
1. Retrieve list of nodes without wrapping with some parent ConfigurationSection
2. Retrieve KeyValue collection of node
Is there some obvious way here? Or it's just such complicated as I think?

Related

How I access app settings key inside web.config

I have many services with the same main path, so I'm looking to add the main path to app settings keys and access it on baseAddress.
just as below code, what I could use instead of {baseAddress}?
<appSettings>
<add key="baseAddresses"value="https://localhost:4434/X/"/>
</appSettings>
<service name="X.Services.Proxy.MOF" behaviorConfiguration="restServiceBehave">
<host>
<baseAddresses>
<add baseAddress="{baseAddresses}/MOF.svc" />
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="rest" bindingConfiguration="NormalRequestBinding" contract="X.Services.Proxy.MOF" name="MOF" />
</service>
You can do it:
ConfigurationManager.AppSettings["{your_key}"]

Queue showing empty

So this is pretty new to me and I'm making progress. I currently have a wcf service using netmsmqbinding to send a simple message to a queue. Everything runs smooth and the event view even says that the message was put in the queue. Although when I goto the actual queue there is nothing in there. I have a service, service host, and asp web app. Note in the web app I have a service reference to the service. Also in the msmq log in the event viewer I get 3 events. Any assistance would be appreciated. Thanks.
Here's my setup.
Service Interface:
[ServiceContract]
public interface IMSMQService
{
[OperationContract(IsOneWay = true)]
void ShowMessage(string msg);
}
Service:
public class MSMQService : IMSMQService
{
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void ShowMessage(string msg)
{
Debug.WriteLine(msg + " Received at: " + System.DateTime.Now.ToString());
}
}
App.Config of Service:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
<appSettings>
<!-- use appSetting to configure MSMQ queue name -->
<add key="queueName" value=".\private$\TestQueue"/>
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
<system.serviceModel>
<services>
<service name="MSMQNoSecurityService.MSMQService" behaviorConfiguration="MyBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9001/msmq"/>
</baseAddresses>
</host>
<endpoint address="net.msmq://localhost/private/TestQueue" binding="netMsmqBinding" bindingConfiguration="MyBinding" contract="MyService.IMSMQService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<serviceMetadata httpGetEnabled="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netMsmqBinding>
<binding name="MyBinding">
<security mode="None"/>
</binding>
</netMsmqBinding>
</bindings>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
Service Host
static void Main(string[] args)
{
ServiceHost svcHost = null;
try
{
// Get MSMQ queue name from appsettings in configuration.
string queueName = ConfigurationManager.AppSettings["queueName"];
// Create the transacted MSMQ queue if necessary.
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName, true);
svcHost = new ServiceHost(typeof(MyService.MSMQService));
svcHost.Open();
Console.WriteLine("\n\nService is Running at following address");
Console.WriteLine("\nhttp://localhost:9001/MSMQService");
}
catch (Exception eX)
{
svcHost = null;
Console.WriteLine("Service can not be started \n\nError Message [" + eX.Message + "]");
}
if (svcHost != null)
{
Console.WriteLine("\nPress any key to close the Service");
Console.ReadKey();
svcHost.Close();
svcHost = null;
}
}
App.Config of Service Host:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
<appSettings>
<add key="queueName" value=".\private$\TestQueue"/>
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<services>
<service name="MyService.MSMQService" behaviorConfiguration="MyBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9001/msmq"/>
</baseAddresses>
</host>
<endpoint address="net.msmq://localhost/private/TestQueue" binding="netMsmqBinding" bindingConfiguration="MyBinding" contract="MyService.IMSMQService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netMsmqBinding>
<binding name="MyBinding" >
<security mode="None"/>
</binding>
</netMsmqBinding>
</bindings>
</system.serviceModel>
</configuration>
MVC Controller
public class WcfMsmqController : Controller
{
public ActionResult Index()
{
MSMQServiceClient proxy = new MSMQServiceClient();
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
proxy.ShowMessage("test");
scope.Complete();
}
proxy.Close();
return View();
}
}
Service model in Web.config (autogenerated):
<system.serviceModel>
<bindings>
<netMsmqBinding>
<binding name="NetMsmqBinding_IMSMQService">
<security mode="None" />
</binding>
</netMsmqBinding>
</bindings>
<client>
<endpoint address="net.msmq://localhost/private/TestQueue" binding="netMsmqBinding"
bindingConfiguration="NetMsmqBinding_IMSMQService" contract="ServiceReference1.IMSMQService"
name="NetMsmqBinding_IMSMQService" />
</client>
</system.serviceModel>
Events from MSMQ Log: Modified some of it for viewing on here
Message with ID CN=msmq,CN=blah,OU=blah,OU=blah,DC=blah,DC=local\8280 was sent to queue PRIVATE=blah
Message with ID CN=msmq,CN=blah,OU=blah,OU=blah,DC=blah,DC=local\8280 was put into queue PRIVATE=blah
Message received
It seems to be related to your transaction.
You should try to place [TransactionFlow(TransactionFlowOption.Allowed)] on the operation in the service contract. Something like:
[ServiceContract]
public interface IMSMQService
{
[OperationContract(IsOneWay = true)]
[TransactionFlow(TransactionFlowOption.Allowed)]
void ShowMessage(string msg);
}
Anyway, you should be aware of local transactions if you decide to deploy this on web farm or something that involves multiple computers.
Figured it out. I had to add a namespace to the servicecontract. Prior it would default to some kind of tempuri.
[ServiceContract(Namespace = "http://MyService")]
public interface IMSMQService
{
[OperationContract(IsOneWay = true)]
[TransactionFlow(TransactionFlowOption.Allowed)]
void ShowMessage(string msg);
}

WCF Error - Object reference not set to an instance of an object. Production service not working

I'm new to writing questions, long time reader. If I omit something please let me know.
I have looked through many different scenario's and possible fixes and have been unable to get my WCF Service working correctly.
My service is responsible for passing data from many different sets to a master repository. The client gathers the data at the local set level and passes it to the service which inserts the data and passes back a result message. Again in the test environment this worked normally.
In production I added the service to an off-site server and configured the client on a remote set. The client was able to configure and receive updates from the service. Up until now everything worked correctly. However once the client attempted to transfer data across it received the following error "Object reference not set to an instance of an object."
Through bug checking I have confirmed there are no connection string issues to the db. I ran the same data transfer again in my test environment with no issues. I was able to connect to the .svc url on the local set.
I've added logging at different points through the data contract method call and none of these logs have triggered any results. I've also tested the write functionality on a test app which confirmed there were no issues with credentials writing to the temp folder. Eg:
public Result InsertVenueRecord(Venue v)
{
System.IO.File.WriteAllText(#"C:\temp\MadeItToVenue" + DateTime.Now.Ticks.ToString() + ".log.txt", "insertVenue()\r\n\r\n");
int oldId = v.VenueId;
try
{
System.IO.File.WriteAllText(#"C:\temp\MadeItToVenue" + DateTime.Now.Ticks.ToString() + ".log.txt", "insertVenue()\r\n\r\n");
//Check Address
if (v.Address.AddressId != 0)
The client app.Config looks as follows:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_placeholder" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="Removed" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_placeholder" contract="placeholder.placeholder"
name="BasicHttpBinding_placeholder" />
</client>
</system.serviceModel>
<appSettings>
<add key="DTFirstWave" value="Venue|Event|EventSurveyLocation|Agent|LoginHistory|LoginUsed"/>
</appSettings>
<connectionStrings>
<!-- Removed Connection Strings -->
</connectionStrings>
</configuration>
The service webconfig looks as follows:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<httpRuntime/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding allowCookies="true" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="52428800" maxArrayLength="52428800" maxBytesPerRead="52428800" maxNameTableCharCount="52428800"/>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
<connectionStrings>
<!--Removed -->
</connectionStrings>
</configuration>
I'm at a loss as to why this isn't working.
plz enable your service SVC log by just add system.daignostics in your service config.It will give you proper error on production.
It will create "App_tracelog.svclog" file in your service dir.
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
<source name="System.ServiceModel" switchValue="Verbose,ActivityTracing">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
<source name="System.Runtime.Serialization" switchValue="Verbose,ActivityTracing">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="App_tracelog.svclog" type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="ServiceModelTraceListener" traceOutputOptions="Timestamp" />
</sharedListeners>

WCF and SimpleMembershipProvider. How to manage users?

I have ASP.NET MVC 4 application with user authentication based on SimpleMemebershipProvider. Using Ms SQL database. Everything works fine. I can register new users, log in, log-out etc.
The problem is that I want to create Windows forms application which can connect to the server and after passing credentials it can validate if user exists in database (registered through MVC) and if so, do some stuff, for example change username or password. My idea is to use WCF service library. I know the basic idea of WCF or at least i hope so :) I know that there is possibility to authenticate users.
I was searching the web but i didn't found how to do this with simplememebership provider. I've also tried to write WCF Service library on my own and I've created something like this below but it doesn't work. When I'm testing and put wrong credentials it returns string "bad credentials" which is good. However when i type in valid credentials it shows me an error "NullReference exception" on line:
if (WebSecurity.Login(UserName, password, persistCookie: false)).
I don't think it's secure either :/
Can somebody explain me how to this or what I'm doing wrong ?? Or maybe there is better solution than WCF ?
Sevice1.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using WebMatrix.WebData;
using System.Web.Mvc;
namespace AR_WCF_Library
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
public class Service1 : IService1
{
public string GetData(string UserName, string password)
{
WebSecurity.InitializeDatabaseConnection("MyDB", "UserProfile", "UserId", "UserName", autoCreateTables: false);
if (WebSecurity.Login(UserName, password, persistCookie: false))
{
return string.Format("Hello: {0}", UserName);
}
else
{
return "bad credentials";
}
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<connectionStrings>
<add name="MyDB" connectionString="Data Source=SERWER\MORPHEUS;Initial Catalog=AOR;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" />
<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<clear/>
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear/>
<add name="SimpleMembershipProvider"
type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"
enablePasswordReset="true" />
</providers>
</membership>
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="AR_WCF_Library.Service1">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8733/Design_Time_Addresses/AR_WCF_Library/Service1/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="wsHttpBinding" contract="AR_WCF_Library.IService1">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Add the following to the Web.config of whatever hosts your WCF service:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>

WCF: StackoverFlow exception

I am getting an exception when trying to servialize the .NET ServiceController class. It serializes fine when it's null but once I populate it I get a stackoverflow exception.
So this works:
[DataMember]
public ServiceController MyServiceController
{
get { return null; }
}
But this gives the error "An unhandled exception of type 'System.StackOverflowException' occurred in System.ServiceProcess.dll":
public class TestClass
{
private ServiceController _serviceController;
[DataMember]
public ServiceController MyServiceController
{
get { return ServiceController.GetServices()[0];
}
}
A strange thing is that there is no error in the logs at all. When there is an error I can see it in the logs so it's not because my logs aren't working. Here is my config file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyCompany.Wcf.RdbmsServer.RdbmsServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyCompany.Wcf.RdbmsServer.RdbmsServiceBehavior"
name="MyCompany.Wcf.RdbmsServer.RdbmsService">
<endpoint address="" binding="wsHttpBinding" contract="MyCompany.Wcf.RdbmsServer.IRdbmsService" bindingConfiguration="IncreaseMaxMessageSize">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/MyCompany.Wcf.RdbmsServer/RdbmsService/" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="IncreaseMaxMessageSize"
maxReceivedMessageSize="655360000">
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="All"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "c:\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
</configuration>
Here is my service interface
[ServiceContract]
public interface IRdbmsService
{
[OperationContract]
TestClass GetServiceControllerList();
}
And the implementation is:
public TestClass GetServiceControllerList()
{
return new TestClass();
}
Any ideas?
You are causing the serializer to recurse:
public class TestClass
{
private ServiceController _serviceController;
[DataMember]
public ServiceController MyServiceController
{
get { return ServiceController.GetServices()[0]; // <-- this returns your service
}
}
The service this is returning is your IRdbmsService, which returns TestClass. This then needs to be serialized, etc.
Edit: To clarify:
When TestClass is serialized, the serializer looks at all of its DataMember properties, one of which is ServiceController. It then serializes this property, which does this on the get:
return ServiceController.GetServices()[0];
Since IRdbmsService is the only service defined in your scope, it is at index 0 from the response of the GetServices call, so it then must be serialized. Since the return type of GetServiceControllerList is TestClass, TestClass must then be serialized, which brings us back to the beginning (hence, the recursion).
As far as how to go about solving this, it depends on what you are trying to do. What this service is doing at the moment is returning information about itself to the caller, which doesn't make sense to me; the caller already has this information at the time of consumption (before making the call). Can you clarify your intent?
Yes, in the constructor of ServiceController CLASS, you are problably calling something recursive which don't have a condition to stop, so every time it calls something recursive, the program push to a stack, and as I said there is no stop condition, it will add to stack untill the memory explode, so it gives this error name StackOverFlow.
A suggestion: Add a break point to debug where its calling recursive. It's so easy when debugging.

Categories

Resources