Configuration branch

This commit is contained in:
2025-10-11 09:44:08 -04:00
parent 0e59b296a3
commit b9a2709fd5
31 changed files with 1367 additions and 1057 deletions
+16 -42
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -14,23 +14,9 @@
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -40,7 +26,6 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -49,51 +34,40 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="HtmlAgilityPack, Version=1.3.0.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>References\HtmlAgilityPack.dll</HintPath>
</Reference>
<Reference Include="Oracle.DataAccess, Version=2.102.2.20, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>References\Oracle.DataAccess.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Management" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="HtmlEndpoint.cs" />
<Compile Include="IEndpoint.cs" />
<Compile Include="HtmlEndpointConfiguration.cs" />
<Compile Include="HttpEndpointConfiguration.cs" />
<Compile Include="IHttpEndpointConfiguration.cs" />
<Compile Include="OracleEndpoint.cs" />
<Compile Include="OracleEndpointConfiguration.cs" />
<Compile Include="IServiceEndpointConfiguration.cs" />
<Compile Include="HttpEndpoint.cs" />
<Compile Include="IServiceEndpoint.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceEndpointFactory.cs" />
<Compile Include="SoapEndpointConfiguration.cs" />
<Compile Include="SoapEndpoint.cs" />
<Compile Include="Status.cs" />
<Compile Include="StatusComparer.cs" />
<Compile Include="WindowsServiceEndpoint.cs" />
<Compile Include="WmiEndpoint.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
+35 -37
View File
@@ -6,36 +6,15 @@ using HtmlAgilityPack;
namespace Endpoint
{
/// <summary>
/// A website endpoint
/// </summary>
public class HtmlEndpoint : HttpEndpoint
{
/// <summary>
/// Gets or sets the xpath query for the html document
/// </summary>
/// <value>The xpath query.</value>
public string XpathQuery { get; set; }
/// <summary>
/// Gets or sets the expected query results.
/// </summary>
/// <value>The expected query results.</value>
public string ExpectedXpathResult { get; set; }
/// <summary>
/// Gets or sets the post.
/// </summary>
/// <value>The post.</value>
public string RequestContent { get; set; }
/// <summary>
/// Returns the HTML parsed into a standard <see cref="XmlDocument"/>.
/// Uses the <see cref="HtmlAgilityPack"/> library for "out of the web" (poorly formatted) html file support.
/// Returns the HTML parsed into a standard XmlDocument.
/// Uses the HtmlAgilityPack library for "out of the web" (poorly formatted) html file support.
/// </summary>
/// <param name="html">The HTML</param>
/// <returns>An <see cref="XmlDocument"/> from the HTML</returns>
private static XmlDocument getHtmlXml(string html)
/// <returns>An XmlDocument from the HTML</returns>
private static XmlDocument GetHtmlXml(string html)
{
var htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml(html);
@@ -58,15 +37,34 @@ namespace Endpoint
}
/// <summary>
/// Returns the HTML grabbed from the passed in URL parsed into a standard <see cref="XmlDocument"/>.
/// Uses the <see cref="HtmlAgilityPack"/> library for "out of the web" html file support.
/// Returns the HTML grabbed from the passed in URL parsed into a standard XmlDocument.
/// Uses the HtmlAgilityPack library for "out of the web" html file support.
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="requestContent">The post data.</param>
/// <returns>An <see cref="XmlDocument"/> from the HTML</returns>
private static XmlDocument getHtmlXml(Uri url, string requestContent)
/// <returns>An XmlDocument from the HTML</returns>
private static XmlDocument GetHtmlXml(Uri url, string requestContent)
{
return GetHtmlXml(GetUrlContent(url, "application/x-www-form-urlencoded", requestContent, null));
}
/// <summary>
/// Gets the HTTP endpoint configuration.
/// </summary>
/// <value>The HTTP endpoint configuration.</value>
public HtmlEndpointConfiguration HtmlEndpointConfiguration
{
get { return (HtmlEndpointConfiguration)_httpEndpointConfiguration; }
}
/// <summary>
/// Initializes a new instance of the <see cref="HttpEndpoint"/> class.
/// </summary>
/// <param name="config">The HttpEndpointConfiguration.</param>
public HtmlEndpoint(HtmlEndpointConfiguration config)
: base(config)
{
return getHtmlXml(GetUrlContent(url, "application/x-www-form-urlencoded", requestContent, null));
}
/// <summary>
@@ -75,29 +73,29 @@ namespace Endpoint
/// <returns>Status</returns>
public override Status GetStatus()
{
var baseStatus = base.GetStatus();
Status baseStatus = base.GetStatus();
if (baseStatus != Status.Up)
return baseStatus;
try
{
var xml = getHtmlXml(Uri, RequestContent);
XmlDocument xml = GetHtmlXml(HttpEndpointConfiguration.Uri, HtmlEndpointConfiguration.RequestContent);
// xml.Save(@"c:\test.xml");
var nodes = xml.SelectNodes(XpathQuery);
XmlNodeList nodes = xml.SelectNodes(HtmlEndpointConfiguration.XpathQuery);
// verify html has expected value
if (nodes == null || nodes.Count == 0)
{
StatusDescription = "Couldn't find expected value in html";
return Status.Error;
}
var value = nodes[0].Value.Trim();
if (value != ExpectedXpathResult)
string value = nodes[0].Value.Trim();
if (value != HtmlEndpointConfiguration.ExpectedXpathResult)
{
StatusDescription = String.Format("Result was: '{0}', was expecting '{1}'", value,
ExpectedXpathResult);
HtmlEndpointConfiguration.ExpectedXpathResult);
return Status.Error;
}
}
+114
View File
@@ -0,0 +1,114 @@
using System;
using System.Configuration;
using System.Xml.Serialization;
namespace Endpoint
{
/// <summary>
/// Defines a configuration for an html webpage endpoint
/// </summary>
public class HtmlEndpointConfiguration : ConfigurationElement, IHttpEndpointConfiguration
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
[ConfigurationProperty("name", DefaultValue = "", IsKey = true, IsRequired = true)]
public string Name
{
get { return (string)base["name"]; }
set { base["name"] = value; }
}
/// <summary>
/// URI of the service
/// </summary>
[XmlIgnore]
public Uri Uri
{
get { return new Uri(UriString); }
}
/// <summary>
/// Gets or sets the URI string.
/// </summary>
/// <value>The URI string.</value>
[ConfigurationProperty("uri", DefaultValue = "", IsKey = false, IsRequired = true)]
public string UriString
{
get { return (string)base["uri"]; }
set { base["uri"] = value; }
}
/// <summary>
/// Gets or sets the xpath query for the html document
/// </summary>
/// <value>The xpath query.</value>
[ConfigurationProperty("xpathQuery", DefaultValue = "", IsKey = false, IsRequired = true)]
public string XpathQuery
{
get { return (string)base["xpathQuery"]; }
set { base["xpathQuery"] = value; }
}
/// <summary>
/// Gets or sets the expected query results.
/// </summary>
/// <value>The expected query results.</value>
[ConfigurationProperty("expectedXpathResult", DefaultValue = "", IsKey = false, IsRequired = true)]
public string ExpectedXpathResult
{
get { return (string)base["expectedXpathResult"]; }
set { base["expectedXpathResult"] = value; }
}
/// <summary>
/// Gets or sets the post.
/// </summary>
/// <value>The post.</value>
[ConfigurationProperty("requestContent", DefaultValue = "", IsKey = false, IsRequired = false)]
public string RequestContent
{
get { return (string)base["requestContent"]; }
set { base["requestContent"] = value; }
}
}
/// <summary>
///
/// </summary>
public class HtmlEndpointConfigurationCollection : ConfigurationElementCollection
{
/// <summary>
/// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement" />.
/// </summary>
/// <returns>
/// A new <see cref="T:System.Configuration.ConfigurationElement" />.
/// </returns>
protected override ConfigurationElement CreateNewElement()
{
return new HtmlEndpointConfiguration();
}
/// <summary>
/// Gets the element key for a specified configuration element when overridden in a derived class.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object" /> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement" />.
/// </returns>
/// <param name="element">The <see cref="T:System.Configuration.ConfigurationElement" /> to return the key for. </param>
protected override object GetElementKey(ConfigurationElement element)
{
return ((HtmlEndpointConfiguration)element).Name;
}
}
/// <summary>
///
/// </summary>
public class HtmlEndpointConfigurationSection : ConfigurationSection
{
[ConfigurationProperty("endpoints")]
public HtmlEndpointConfigurationCollection Endpoints { get { return (HtmlEndpointConfigurationCollection)(base["endpoints"]); } }
}
}
+69 -45
View File
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Collections.Generic;
namespace Endpoint
{
@@ -10,66 +10,50 @@ namespace Endpoint
/// Http Endpoint - such as a webserver, a webservice, etc
/// </summary>
[Serializable]
public class HttpEndpoint : IEndpoint
public class HttpEndpoint : IServiceEndpoint
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }
/// <summary>
/// URI of the service
/// </summary>
public Uri Uri { get; set; }
/// <summary>
/// Gets or sets the URI string.
/// </summary>
/// <value>The URI string.</value>
public string UriString
{
get { return Uri.ToString(); }
set { Uri = new Uri(value); }
}
/// <summary>
/// Returns the response string grabbed from the passed in URL.
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="contentType">The HTTP content type.</param>
/// <param name="contentType">The HTTP contentType.</param>
/// <param name="requestContent">The request content.</param>
/// <param name="webHeaders">The web headers.</param>
/// <returns>A string containing response</returns>
protected static string GetUrlContent(Uri url, string contentType, string requestContent,
Dictionary<string, string> webHeaders)
protected static string GetUrlContent(Uri url, string contentType, string requestContent, Dictionary<string,string> webHeaders)
{
// POST request
if (!string.IsNullOrEmpty(contentType) && !string.IsNullOrEmpty(requestContent))
{
var webRequest = (HttpWebRequest) WebRequest.Create(url);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
// NOTE: need a proxy? Here's where it would go
// NOTE: proxy?
// webRequest.Proxy = new WebProxy();
// SOAP
webRequest.ContentType = contentType;
if (webHeaders != null && webHeaders.Count > 0)
{
foreach (var webHeader in webHeaders)
foreach (KeyValuePair<string, string> webHeader in webHeaders)
webRequest.Headers.Add(webHeader.Key, webHeader.Value);
}
// NOTE: SOAPACtion
//webRequest.Headers.Add("SOAPAction", "\"urn:getPaymentKey\"");
// FORM
//webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "POST";
// webRequest.Accept = "text/xml";
//We need to count how many bytes we're sending. Post'ed Faked Forms should be name=value&
var bytes = Encoding.ASCII.GetBytes(requestContent);
byte[] bytes = Encoding.ASCII.GetBytes(requestContent);
webRequest.ContentLength = bytes.Length;
using (var requestStream = webRequest.GetRequestStream())
using (Stream requestStream = webRequest.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length); //write it to the stream
}
var webResponse = webRequest.GetResponse();
WebResponse webResponse = webRequest.GetResponse();
if (webResponse == null)
return null;
using (var streamReader = new StreamReader(webResponse.GetResponseStream()))
@@ -80,18 +64,46 @@ namespace Endpoint
// GET Request
var client = new WebClient();
using (var data = client.OpenRead(url))
using (Stream data = client.OpenRead(url))
using (var reader = new StreamReader(data))
{
return reader.ReadToEnd();
}
}
protected readonly IHttpEndpointConfiguration _httpEndpointConfiguration;
/// <summary>
/// Returns a string explaining details on the current status
/// </summary>
/// <returns>string with status message</returns>
public virtual string StatusDescription { get; protected set; }
public virtual string StatusDescription
{
get; protected set;
}
public IServiceEndpointConfiguration ServiceEndpointConfiguration
{
get { return _httpEndpointConfiguration; }
}
/// <summary>
/// Gets the service name
/// </summary>
/// <value></value>
public string ServiceName
{
get { return _httpEndpointConfiguration.Name; }
}
/// <summary>
/// Gets the HTTP endpoint configuration.
/// </summary>
/// <value>The HTTP endpoint configuration.</value>
public IHttpEndpointConfiguration HttpEndpointConfiguration
{
get { return _httpEndpointConfiguration; }
}
/// <summary>
/// Gets the current status result of the endpoint
@@ -101,24 +113,36 @@ namespace Endpoint
{
try
{
var request = WebRequest.Create(Uri);
WebRequest request = WebRequest.Create(HttpEndpointConfiguration.Uri);
using (var response = (HttpWebResponse) request.GetResponse())
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
StatusDescription = response.StatusDescription;
return response.StatusCode == HttpStatusCode.OK
? Status.Up
: Status.Unreachable;
if (response.StatusCode == HttpStatusCode.OK)
return Status.Up;
return Status.Unreachable;
}
}
catch (WebException ex)
{
StatusDescription = ex.Message + " (" + ex.Status + ")";
return ex.Status == WebExceptionStatus.Timeout
? Status.Timeout
: Status.Unreachable;
// TODO: LOG
if (ex.Status == WebExceptionStatus.Timeout)
{
return Status.Timeout;
}
return Status.Unreachable;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="HttpEndpoint"/> class.
/// </summary>
/// <param name="config">The HttpEndpointConfiguration.</param>
public HttpEndpoint(IHttpEndpointConfiguration config)
{
_httpEndpointConfiguration = config;
}
}
}
+128
View File
@@ -0,0 +1,128 @@
using System;
using System.Configuration;
using System.Xml.Serialization;
namespace Endpoint
{
/// <summary>
/// Defines a configuration for an http service endpoint
/// </summary>
public class HttpEndpointConfiguration : ConfigurationElement, IHttpEndpointConfiguration
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
[ConfigurationProperty("name", DefaultValue = "", IsKey = true, IsRequired = true)]
public string Name
{
get { return (string) base["name"]; }
set { base["name"] = value; }
}
/// <summary>
/// URI of the service
/// </summary>
[XmlIgnore]
public Uri Uri
{
get { return new Uri((string) base["uri"]); }
}
/// <summary>
/// Gets or sets the URI string.
/// </summary>
/// <value>The URI string.</value>
[ConfigurationProperty("uri", DefaultValue = "", IsKey = false, IsRequired = true)]
public string UriString
{
get { return (string)base["uri"]; }
set { base["uri"] = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref="HttpEndpointConfiguration"/> class.
/// </summary>
/// <param name="serviceName">The name.</param>
/// <param name="uri">The uri.</param>
public HttpEndpointConfiguration(string serviceName, Uri uri)
{
Name = serviceName;
UriString = uri.OriginalString;
}
/// <summary>
/// Initializes a new instance of the <see cref="HttpEndpointConfiguration"/> class.
/// </summary>
internal protected HttpEndpointConfiguration()
{
}
/// <summary>
/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
/// </summary>
/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
/// <returns>
/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
/// </returns>
/// <exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.</exception>
public override bool Equals(object obj)
{
HttpEndpointConfiguration value = obj as HttpEndpointConfiguration;
if (value == null)
return false;
if (value.Uri != Uri)
return false;
return true;
}
/// <summary>
/// Serves as a hash function for a particular type.
/// </summary>
/// <returns>
/// A hash code for the current <see cref="T:System.Object"/>.
/// </returns>
public override int GetHashCode()
{
return Uri.GetHashCode();
}
}
/// <summary>
///
/// </summary>
public class HttpEndpointConfigurationCollection : ConfigurationElementCollection
{
/// <summary>
/// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement" />.
/// </summary>
/// <returns>
/// A new <see cref="T:System.Configuration.ConfigurationElement" />.
/// </returns>
protected override ConfigurationElement CreateNewElement()
{
return new HttpEndpointConfiguration();
}
/// <summary>
/// Gets the element key for a specified configuration element when overridden in a derived class.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object" /> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement" />.
/// </returns>
/// <param name="element">The <see cref="T:System.Configuration.ConfigurationElement" /> to return the key for. </param>
protected override object GetElementKey(ConfigurationElement element)
{
return ((HttpEndpointConfiguration) element).Name;
}
}
/// <summary>
///
/// </summary>
public class HttpEndpointConfigurationSection : ConfigurationSection
{
[ConfigurationProperty("endpoints")]
public HttpEndpointConfigurationCollection Endpoints { get { return (HttpEndpointConfigurationCollection)(base["endpoints"]); } }
}
}
+18
View File
@@ -0,0 +1,18 @@
using System;
using System.Configuration;
using System.Xml.Serialization;
namespace Endpoint
{
public interface IHttpEndpointConfiguration : IServiceEndpointConfiguration
{
/// <summary>
/// URI of the service
/// </summary>
[XmlIgnore]
Uri Uri { get; }
[ConfigurationProperty("uri", DefaultValue = "", IsKey = false, IsRequired = false)]
string UriString { get; set; }
}
}
+31
View File
@@ -0,0 +1,31 @@
namespace Endpoint
{
/// <summary>
/// Describes a service endpoint, and the methods to find its current status
/// </summary>
public interface IServiceEndpoint
{
/// <summary>
/// Configuration of the endpoint
/// </summary>
IServiceEndpointConfiguration ServiceEndpointConfiguration { get; }
/// <summary>
/// Gets the service name
/// </summary>
string ServiceName { get; }
/// <summary>
/// Gets the current status result of the endpoint
/// </summary>
/// <returns>Status</returns>
Status GetStatus();
/// <summary>
/// Returns a string explaining details on the current status
/// </summary>
/// <returns>string with status message</returns>
string StatusDescription { get; }
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace Endpoint
{
/// <summary>
/// Describes a service endpoint's configuration
/// </summary>
public interface IServiceEndpointConfiguration
{
string Name { get; set; }
}
}
+60
View File
@@ -0,0 +1,60 @@
using System;
using Oracle.DataAccess.Client;
namespace Endpoint
{
public class OracleEndpoint : IServiceEndpoint
{
private readonly OracleEndpointConfiguration _serviceEndpointConfiguration;
public IServiceEndpointConfiguration ServiceEndpointConfiguration
{
get { return _serviceEndpointConfiguration; }
}
public string ServiceName
{
get { return _serviceEndpointConfiguration.Name; }
}
public string StatusDescription { get; private set; }
public Status GetStatus()
{
using (OracleConnection oracleConnection = new OracleConnection(_serviceEndpointConfiguration.ConnectionString))
using (OracleCommand oracleCommand = new OracleCommand(_serviceEndpointConfiguration.ScalarQueryString, oracleConnection))
{
try
{
oracleConnection.Open();
object result = oracleCommand.ExecuteScalar();
string resultString = result.ToString();
if (resultString != _serviceEndpointConfiguration.ExpectedQueryResult)
{
StatusDescription = String.Format("Result was: '{0}', was expecting '{1}'", resultString,
_serviceEndpointConfiguration.ExpectedQueryResult);
return Status.Error;
}
}
catch(Exception ex)
{
StatusDescription = ex.Message;
return Status.Error;
}
}
StatusDescription = "OK";
return Status.Up;
}
/// <summary>
/// Initializes a new instance of the <see cref="OracleEndpoint"/> class.
/// </summary>
/// <param name="config">The config.</param>
public OracleEndpoint(OracleEndpointConfiguration config)
{
_serviceEndpointConfiguration = config;
StatusDescription = "";
}
}
}
+155
View File
@@ -0,0 +1,155 @@
using System;
using System.Configuration;
namespace Endpoint
{
/// <summary>
/// Defines a configuration for an oracle service endpoint
/// </summary>
public class OracleEndpointConfiguration : ConfigurationElement, IServiceEndpointConfiguration
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
[ConfigurationProperty("name", DefaultValue = "", IsKey = true, IsRequired = true)]
public string Name
{
get { return (string)base["name"]; }
set { base["name"] = value; }
}
/// <summary>
/// Gets or sets the connection string.
/// </summary>
/// <value>The connection string.</value>
[ConfigurationProperty("connectionString", DefaultValue = "", IsKey = false, IsRequired = true)]
public string ConnectionString
{
get { return (string)base["connectionString"]; }
set { base["connectionString"] = value; }
}
/// <summary>
/// Gets or sets the connection string.
/// </summary>
/// <value>The connection string.</value>
[ConfigurationProperty("scalarQueryString", DefaultValue = "", IsKey = false, IsRequired = true)]
public string ScalarQueryString
{
get { return (string)base["scalarQueryString"]; }
set { base["scalarQueryString"] = value; }
}
/// <summary>
/// Gets or sets the connection string.
/// </summary>
/// <value>The connection string.</value>
[ConfigurationProperty("expectedQueryResult", DefaultValue = "", IsKey = false, IsRequired = true)]
public string ExpectedQueryResult
{
get { return (string)base["expectedQueryResult"]; }
set { base["expectedQueryResult"] = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref="OracleEndpointConfiguration"/> class.
/// </summary>
internal protected OracleEndpointConfiguration()
{}
/// <summary>
/// Initializes a new instance of the <see cref="OracleEndpointConfiguration"/> class.
/// </summary>
/// <param name="serviceName">Name of the service.</param>
/// <param name="connectionString">The connection string.</param>
/// <param name="scalarQueryString">The scalar query string.</param>
/// <param name="expectedQueryResult">The expected query result.</param>
public OracleEndpointConfiguration(string serviceName, string connectionString, string scalarQueryString, string expectedQueryResult)
{
if (serviceName == null)
throw new ArgumentNullException("serviceName");
if (connectionString == null)
throw new ArgumentNullException("connectionString");
if (scalarQueryString == null)
throw new ArgumentNullException("scalarQueryString");
if (expectedQueryResult == null)
throw new ArgumentNullException("expectedQueryResult");
ConnectionString = connectionString;
ScalarQueryString = scalarQueryString;
ExpectedQueryResult = expectedQueryResult;
}
/// <summary>
/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
/// </summary>
/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
/// <returns>
/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
/// </returns>
/// <exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.</exception>
public override bool Equals(object obj)
{
OracleEndpointConfiguration value = obj as OracleEndpointConfiguration;
if (value == null)
return false;
if (value.ConnectionString != ConnectionString || value.ScalarQueryString != ScalarQueryString)
return false;
return true;
}
/// <summary>
/// Serves as a hash function for a OracleEndpointConfiguration.
/// </summary>
/// <returns>
/// A hash code for the current <see cref="T:System.Object"/>.
/// </returns>
public override int GetHashCode()
{
return ConnectionString.GetHashCode() ^ ScalarQueryString.GetHashCode();
}
}
/// <summary>
///
/// </summary>
public class OracleEndpointConfigurationCollection : ConfigurationElementCollection
{
/// <summary>
/// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement" />.
/// </summary>
/// <returns>
/// A new <see cref="T:System.Configuration.ConfigurationElement" />.
/// </returns>
protected override ConfigurationElement CreateNewElement()
{
return new OracleEndpointConfiguration();
}
/// <summary>
/// Gets the element key for a specified configuration element when overridden in a derived class.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object" /> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement" />.
/// </returns>
/// <param name="element">The <see cref="T:System.Configuration.ConfigurationElement" /> to return the key for. </param>
protected override object GetElementKey(ConfigurationElement element)
{
return ((OracleEndpointConfiguration)element).Name;
}
}
/// <summary>
///
/// </summary>
public class OracleEndpointConfigurationSection : ConfigurationSection
{
/// <summary>
/// Gets the endpoints.
/// </summary>
/// <value>The endpoints.</value>
[ConfigurationProperty("endpoints")]
public OracleEndpointConfigurationCollection Endpoints { get { return (OracleEndpointConfigurationCollection)(base["endpoints"]); } }
}
}
+31
View File
@@ -0,0 +1,31 @@
using System;
namespace Endpoint
{
/// <summary>
/// ServiceEndpointFactory
/// </summary>
public class ServiceEndpointFactory
{
/// <summary>
/// Creates the service endpoint based on the scheme
/// </summary>
/// <param name="config">The service endpoint configuration.</param>
/// <returns>The service endpoint.</returns>
public static IServiceEndpoint CreateServiceEndpoint(IServiceEndpointConfiguration config)
{
Type type = config.GetType();
if (type == typeof(HtmlEndpointConfiguration))
return new HtmlEndpoint((HtmlEndpointConfiguration)config);
if (type == typeof(HttpEndpointConfiguration))
return new HttpEndpoint((HttpEndpointConfiguration)config);
if (type == typeof(OracleEndpointConfiguration))
return new OracleEndpoint((OracleEndpointConfiguration)config);
throw new ArgumentException("Unknown type: " + type);
}
}
}
+27 -48
View File
@@ -4,92 +4,71 @@ using System.Xml;
namespace Endpoint
{
/// <summary>
/// A SOAP webservice endpoint.
/// </summary>
public class SoapEndpoint : HttpEndpoint
{
private string _xpathNamespaces = string.Empty;
private Dictionary<string, string> _namespaceToUri;
/// <summary>
/// Gets or sets the xpath query for the html document
/// Gets the SOAP endpoint configuration.
/// </summary>
/// <value>The xpath query.</value>
public string XpathQuery { get; set; }
/// <value>The SOAP endpoint configuration.</value>
public SoapEndpointConfiguration SoapEndpointConfiguration
{
get { return (SoapEndpointConfiguration)_httpEndpointConfiguration; }
}
/// <summary>
/// Gets or sets the namespaces used in the xpath query
/// Initializes a new instance of the <see cref="HttpEndpoint"/> class.
/// </summary>
/// <value>The xpath namespaces.</value>
public string XpathNamespaces
/// <param name="config">The SoapEndpointConfiguration.</param>
public SoapEndpoint(SoapEndpointConfiguration config)
: base(config)
{
get { return _xpathNamespaces; }
set
if (!string.IsNullOrEmpty(SoapEndpointConfiguration.XpathNamespaces))
{
_xpathNamespaces = value;
if (string.IsNullOrEmpty(_xpathNamespaces)) return;
var split = _xpathNamespaces.Split(',');
string[] split = SoapEndpointConfiguration.XpathNamespaces.Split(',');
if (split.Length != 2)
throw new ArgumentException("Need a comma separated pair in XpathNamespaces.");
throw new ArgumentException("Need a comma separated pair in XpathNamespaces.", "config");
_namespaceToUri = new Dictionary<string, string>();
_namespaceToUri.Add(split[0], split[1]);
}
}
/// <summary>
/// Gets or sets the expected query results.
/// </summary>
/// <value>The expected query results.</value>
public string ExpectedXpathResult { get; set; }
/// <summary>
/// Gets or sets the SOAP action.
/// </summary>
/// <value>The post.</value>
public string SoapAction { get; set; }
/// <summary>
/// Gets or sets the SOAP request.
/// </summary>
/// <value>The post.</value>
public string SoapRequest { get; set; }
/// <summary>
/// Gets the current status result of the endpoint
/// </summary>
/// <returns>Status</returns>
public override Status GetStatus()
{
var baseStatus = base.GetStatus();
if (baseStatus != Status.Up) // if we can't even get to the webserver, no need to try and call a WS.
Status baseStatus = base.GetStatus();
if (baseStatus != Status.Up)
return baseStatus;
try
{
var headers = new Dictionary<string, string> {{"SOAPAction", SoapAction}};
Dictionary<string, string> headers = new Dictionary<string, string>
{{"SOAPAction", SoapEndpointConfiguration.SoapAction}};
var xml = new XmlDocument();
XmlDocument xml = new XmlDocument();
xml.LoadXml(GetUrlContent(Uri, "text/xml; charset=utf-8", SoapRequest, headers));
xml.LoadXml(GetUrlContent(SoapEndpointConfiguration.Uri, "text/xml; charset=utf-8", SoapEndpointConfiguration.SoapRequest, headers));
XmlNodeList nodes;
if (_namespaceToUri != null)
{
var nsMgr = new XmlNamespaceManager(xml.NameTable);
foreach (var namespaceToUri in _namespaceToUri)
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xml.NameTable);
foreach (KeyValuePair<string, string> namespaceToUri in _namespaceToUri)
{
nsMgr.AddNamespace(namespaceToUri.Key, namespaceToUri.Value);
}
nodes = xml.SelectNodes(XpathQuery, nsMgr);
nodes = xml.SelectNodes(SoapEndpointConfiguration.XpathQuery, nsMgr);
}
else
nodes = xml.SelectNodes(XpathQuery);
nodes = xml.SelectNodes(SoapEndpointConfiguration.XpathQuery);
//xml.Save(@"c:\soap.xml");
// xml.Save(@"c:\soap.xml");
// verify response has expected value
if (nodes == null || nodes.Count == 0)
@@ -97,11 +76,11 @@ namespace Endpoint
StatusDescription = "Couldn't find expected value in SOAP response";
return Status.Error;
}
var value = nodes[0].Value.Trim();
if (value != ExpectedXpathResult)
string value = nodes[0].Value.Trim();
if (value != SoapEndpointConfiguration.ExpectedXpathResult)
{
StatusDescription = String.Format("Result was: '{0}', was expecting '{1}'", value,
ExpectedXpathResult);
SoapEndpointConfiguration.ExpectedXpathResult);
return Status.Error;
}
}
+134
View File
@@ -0,0 +1,134 @@
using System;
using System.Configuration;
using System.Xml.Serialization;
namespace Endpoint
{
public class SoapEndpointConfiguration : ConfigurationElement, IHttpEndpointConfiguration
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
[ConfigurationProperty("name", DefaultValue = "", IsKey = true, IsRequired = true)]
public string Name
{
get { return (string)base["name"]; }
set { base["name"] = value; }
}
/// <summary>
/// URI of the service
/// </summary>
[XmlIgnore]
public Uri Uri
{
get { return new Uri(UriString); }
}
/// <summary>
/// Gets or sets the URI string.
/// </summary>
/// <value>The URI string.</value>
[ConfigurationProperty("uri", DefaultValue = "", IsKey = false, IsRequired = true)]
public string UriString
{
get { return (string)base["uri"]; }
set { base["uri"] = value; }
}
/// <summary>
/// Gets or sets the xpath query for the html document
/// </summary>
/// <value>The xpath query.</value>
[ConfigurationProperty("xpathQuery", DefaultValue = "", IsKey = false, IsRequired = true)]
public string XpathQuery
{
get { return (string)base["xpathQuery"]; }
set { base["xpathQuery"] = value; }
}
/// <summary>
/// Gets or sets the namespaces used in the xpath query
/// </summary>
/// <value>The xpath namespaces.</value>
[ConfigurationProperty("xpathNamespaces", DefaultValue = "", IsKey = false, IsRequired = false)]
public string XpathNamespaces
{
get { return (string)base["xpathNamespaces"]; }
set { base["xpathNamespaces"] = value; }
}
/// <summary>
/// Gets or sets the expected query results.
/// </summary>
/// <value>The expected query results.</value>
[ConfigurationProperty("expectedXpathResult", DefaultValue = "", IsKey = false, IsRequired = true)]
public string ExpectedXpathResult
{
get { return (string)base["expectedXpathResult"]; }
set { base["expectedXpathResult"] = value; }
}
/// <summary>
/// Gets or sets the SOAP action.
/// </summary>
/// <value>The post.</value>
[ConfigurationProperty("soapAction", DefaultValue = "", IsKey = false, IsRequired = true)]
public string SoapAction
{
get { return (string)base["soapAction"]; }
set { base["soapAction"] = value; }
}
/// <summary>
/// Gets or sets the SOAP request.
/// </summary>
/// <value>The post.</value>
[ConfigurationProperty("soapRequest", DefaultValue = "", IsKey = false, IsRequired = true)]
public string SoapRequest
{
get { return (string)base["soapRequest"]; }
set { base["soapRequest"] = value; }
}
}
/// <summary>
///
/// </summary>
public class SoapEndpointConfigurationCollection : ConfigurationElementCollection
{
/// <summary>
/// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement" />.
/// </summary>
/// <returns>
/// A new <see cref="T:System.Configuration.ConfigurationElement" />.
/// </returns>
protected override ConfigurationElement CreateNewElement()
{
return new SoapEndpointConfiguration();
}
/// <summary>
/// Gets the element key for a specified configuration element when overridden in a derived class.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object" /> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement" />.
/// </returns>
/// <param name="element">The <see cref="T:System.Configuration.ConfigurationElement" /> to return the key for. </param>
protected override object GetElementKey(ConfigurationElement element)
{
return ((SoapEndpointConfiguration)element).Name;
}
}
/// <summary>
///
/// </summary>
public class SoapEndpointConfigurationSection : ConfigurationSection
{
[ConfigurationProperty("endpoints")]
public SoapEndpointConfigurationCollection Endpoints { get { return (SoapEndpointConfigurationCollection)(base["endpoints"]); } }
}
}
+2 -6
View File
@@ -3,13 +3,8 @@ namespace Endpoint
/// <summary>
/// Status of an endpoint
/// </summary>
/// <remarks>The <see cref="StatusComparer"/> expects these to be in order of best-to-worst descending.</remarks>
public enum Status
{
/// <summary>
/// Service state is unknown - this will occur only before the first poll.
/// </summary>
Unknown,
/// <summary>
/// Service is working
/// </summary>
@@ -25,6 +20,7 @@ namespace Endpoint
/// <summary>
/// Service is available, but returns an error message
/// </summary>
Error
Error,
Unknown
}
}