I have a App.config file, where I declared a section group ListOfItems and 2 sections Item_A and Item_B:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="ListOfItems">
<section name="Item_A" type="System.Configuration.AppSettingsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
<section name="Item_B" type="System.Configuration.AppSettingsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
</startup>
<ListOfItems>
<Item_A>
<add key="FileAddress" value="http://www.example.com/file1.xml"/>
<add key="FileType" value="xml"/>
<add key="DateFieldFormat" value="yyyy/MM/dd"/>
<add key="MainFolder" value="Folder_A"/>
<add key="OutputFolder" value="output"/>
<add key="ArchiveFolder" value="archive"/>
</Item_A>
<Item_B>
<add key="FileAddress" value="http://www.example.com/file2.txt"/>
<add key="FileType" value="txt"/>
<add key="DateFieldFormat" value="yyyy-MM-dd"/>
<add key="MainFolder" value="Folder_B"/>
<add key="OutputFolder" value="output"/>
<add key="ArchiveFolder" value="archive"/>
</Item_B>
</ListOfItems>
</configuration>
Then I defined a class with properties:
Namespace DataTypes
Friend Class ItemObject
Inherits ConfigurationSection
<ConfigurationProperty("FileAddress", DefaultValue:=Nothing, IsRequired:=True)>
Public Property FileAddressProperty As String
Get
Return CType(Me("FileAddress"), String)
End Get
Protected Friend Set(ByVal value As String)
Me("FileAddress") = value
End Set
End Property
<ConfigurationProperty("FileType", DefaultValue:="xml", IsRequired:=True)>
Public Property FileTypeProperty As String
Get
Return CType(Me("FileType"), String)
End Get
Protected Friend Set(ByVal value As String)
Me("FileType") = value
End Set
End Property
<ConfigurationProperty("DateFieldFormat", DefaultValue:="yyyy/MM/dd", IsRequired:=True)>
Public Property DateFieldFormatProperty As String
Get
Return CType(Me("DateFieldFormat"), String)
End Get
Protected Friend Set(ByVal value As String)
Me("DateFieldFormat") = value
End Set
End Property
<ConfigurationProperty("MainFolder", DefaultValue:="Folder", IsRequired:=True)>
Public Property MainFolderProperty As String
Get
Return CType(Me("MainFolder"), String)
End Get
Protected Friend Set(ByVal value As String)
Me("MainFolder") = value
End Set
End Property
<ConfigurationProperty("OutputFolder", DefaultValue:="output", IsRequired:=True)>
Public Property OutputFolderProperty As String
Get
Return CType(Me("OutputFolder"), String)
End Get
Protected Friend Set(ByVal value As String)
Me("OutputFolder") = value
End Set
End Property
<ConfigurationProperty("ArchiveFolder", DefaultValue:="archive", IsRequired:=True)>
Public Property ArchiveFolderProperty As String
Get
Return CType(Me("ArchiveFolder"), String)
End Get
Protected Friend Set(ByVal value As String)
Me("ArchiveFolder") = value
End Set
End Property
End Class
End Namespace
Now I have looked here and here, but I cannot figure out how to write the following loop:
Foreach item in ListOfItems, create an ItemObject with data from App.config (I would add it to a list of ItemObjects. So I would have a list with 2 items in it, one for Item_A and one for Item_B
Related
Trying to deserialize an XML file but having trouble with sub nodes.
I need to collect these by there ID value eg ConNum, class, recid.
Currently I can get one value back but it's giving me the name of the ID and not the value.
eg: xData.TRAN_DATEX.theTarget = ConNum where I require 20190910 instead.
Here's the XML:
<?xml version="1.0" encoding="UTF-8"?>
<targets>
<target id="ConNum">20190910</target>
<target id="class">Third</target>
<target id="recid">123 </target>
</targets>
Here's my class:
Imports System.Xml.Serialization
<Serializable, XmlRoot("targets")>
Public Class XmlFile
<XmlElement("target")> Public Property TRAN_DATEX As myTarget
End Class
<Serializable, XmlRoot("target")>
Public Class myTarget
<XmlAttribute("id")> Public theTarget As String
End Class
And here is the deserialize method:
Dim fFile As FileInfo = New FileInfo("C:\Temp\TARGETS.metadata")
Dim s As New XmlSerializer(GetType(XmlFile))
Using sr As New StreamReader(fFile.FullName)
xData = s.Deserialize(sr)
Stop
End Using
theTarget is getting the value of the id attribute. You want the XmlText of that element:
<Serializable, XmlRoot("target")>
Public Class myTarget
<XmlAttribute("id")> Public theTarget As String
<XmlText> Public Property theValue As String
End Class
Then, instead of xData.TRAN_DATEX.theTarget, you can use xData.TRAN_DATEX.theValue
Edit: In response to the comment.
As there are multiple <target> elements, TRAN_DATEX will need to be a list:
<Serializable, XmlRoot("targets")>
Public Class XmlFile
<XmlElement("target")> Public Property TRAN_DATEX As New List(Of myTarget)
End Class
LINQ can be used to access the data that is required:
Dim reqValueTarget = xData.TRAN_DATEX.FirstOrDefault(Function(x) x.theTarget = "ConNum")
If reqValueTarget IsNot Nothing then
Dim reqValue = reqValueTarget.theValue
End If
I'm creating configSections in app.config with my custom handler AbraMain.MyConfigHandler
Error:
Could not load type 'AbraMain.MyConfigHandler.ApplicationListCollection' from assembly 'System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.":"AbraMain.MyConfigHandler.ApplicationListCollection"
app.config
<configuration>
<configSections>
<section name="applicationList" type ="AbraMain.MyConfigHandler.ApplicationListCollection"/>
</configSections>
<applicationList>
<add name="Abra Backup" index="0" iconIndex="0" desc="AbraBackup"/>
<add name="Abra Backup" index="0" iconIndex="0" desc="AbraBackup"/>
</applicationList>
</configuration>
MyConfigHandler.vb
Namespace MyConfigHandler
'Desc : Individual Application configuration Class
'Handle Tag : App.config -> <applicationList> -> <add>
Public Class ApplInfoConfig
Inherits ConfigurationElement
<ConfigurationProperty("name", IsRequired:=True)> _
Public Property name() As String
Get
Return CStr(Me("name"))
End Get
Set(ByVal value As String)
Me("name") = value
End Set
End Property
<ConfigurationProperty("desc", DefaultValue:="", IsRequired:=False)> _
Public Property desc() As String
Get
Return CStr(Me("desc"))
End Get
Set(ByVal value As String)
Me("desc") = value
End Set
End Property
<ConfigurationProperty("subPath", DefaultValue:="", IsRequired:=False)> _
Public Property subPath() As String
Get
Return CStr(Me("subPath"))
End Get
Set(ByVal value As String)
Me("subPath") = value
End Set
End Property
<ConfigurationProperty("index", IsRequired:=True)> _
Public Property index() As Integer
Get
Return Me("index")
End Get
Set(ByVal value As Integer)
Me("index") = value
End Set
End Property
<ConfigurationProperty("iconIndex", DefaultValue:="0", IsRequired:=False)> _
Public Property iconIndex() As Integer
Get
Return Me("iconIndex")
End Get
Set(ByVal value As Integer)
Me("iconIndex") = value
End Set
End Property
End Class
'Desc : Collection of Individual Application configuration Class
'Handle Tag : App.config -> <applicationList>
Public Class ApplicationListCollection
Inherits ConfigurationElementCollection
Protected Overloads Overrides Function CreateNewElement() As System.Configuration.ConfigurationElement
Return New ApplInfoConfig()
End Function
Protected Overrides Function GetElementKey(ByVal element As System.Configuration.ConfigurationElement) As Object
Return CType(element, ApplInfoConfig).name()
End Function
End Class
End Namespace
It seems that the problem is in the app.config on the line where you specify the handler for your custom section:
<section name="applicationList" type ="AbraMain.MyConfigHandler.ApplicationListCollection"/>
The type declaration for your custom handler type also needs to include the assembly in which it can be found. Otherwise, it will try to find it in the default System.Configuration assembly. That is also what the error message that you got said.
So you can solve it by including the name of your assembly as well. I am assuming your assembly is named AbraMain. Then you need to change that line to:
<section name="applicationList" type ="AbraMain.MyConfigHandler.ApplicationListCollection, AbraMain"/>
However, you seem to have a second problem. For a configuration section, you need to have a handler that implements ConfigurationSection.
So you need to add a new class to do that:
Public Class ApplicationList
Inherits ConfigurationSection
' You need to do the implementation. There are plenty of
' examples available on-line.
End Class
And then point your app.config to use it:
<section name="applicationList" type ="AbraMain.MyConfigHandler.ApplicationList, AbraMain"/>
I have the following class which I want to serialize to XML:
<Serializable()> _
Public Class Settings
Public Shared var1 As Boolean = False
Public var2 As Boolean = False
End Class
I create a new instance and serialize it using my own method...
SaveSerialXML(PathToFile, New Settings, GetType(Settings))
...however the shared (static) variable is not included in the output:
<?xml version="1.0" encoding="utf-8"?>
<Settings>
<var2>false</var2>
</Settings>
Does anyone know of a way to serialize shared members of a class to XML?
Serialization is about serializing instances. Shared variables do not belong to an instance.
You can cheat add a redirect instance property for serialization.
For example:
Public Property Var1Instance As Boolean
Get
Return Var1
End Get
Set(value As Boolean)
Var1 = value
End Set
End Property
I've often found myself wanting to implement my own Xml serialization and not use the .NET XmlSerializer.
I do so by adding an Xml property to my class that directly handles the serialization via Xml Literals. That property could be a String or an XElement depending on how I'm going to use it.
Here's how the Xml String property would look for your sample class:
Public Property Xml() As String
Get
Return <Settings>
<var1><%= var1 %></var1>
<var2><%= var2 %></var2>
</Settings>.ToString
End Get
Set(ByVal value As String)
Dim xValue = XElement.Parse(value)
var1 = xValue...<var1>.Value = "true"
var2 = xValue...<var2>.Value = "true"
End Set
End Property
This places all the serialization logic in one place and avoids the use of attributes to control how an instance gets serialized. The other benefit I've found is that this allows me to deserialize a class that does not have a default constructor.
In production scenarios I would add an extension method that converts a String to a Boolean instead of comparing to "true" since valid Xml Boolean values include true, false, 1 and 0.
I am trying to access http://localhost/tempservicehost/tempservice.svc and I am getting the following error:
Error Description: 'Resource does not
exist'
This may be because an invalid URI or
HTTP method was specified. Please see
the service help page for constructing
valid requests to the service.
The funny thing is that http://localhost/tempservicehost/tempservice.svc/help is working fine. Not only that, all my endpoints are working fine.
I am using IIS 7.5 (Win 2008 R2). Application developed using .NET 4.0
Post Updated (following is the code):
<ServiceContract()>
Public Interface ITestSvc
<OperationContract()>
<Description("")>
<WebInvoke(Bodystyle:=WebMessageBodyStyle.Bare,
Method:="POST",
UriTemplate:="GetCodes")>
Function GetCodes(ByVal oReq As ReqGetCodes) As RespGetCodes
End Interface
Public Class TestSvc
Implements ITestSvc
Public Function GetCodes(ByVal oReq As ReqGetCodes) As RespGetCodes Implements ITestSvc.GetCodes
Dim o As New RespGetCodes
Dim lstGetCodes = New List(Of ClassGetCodes) From {
New ClassGetCodes With {.App_Code = "a1", .SystemFlag = True},
New ClassGetCodes With {.App_Code = "a2", .SystemFlag = False},
New ClassGetCodes With {.App_Code = "a3", .SystemFlag = True},
New ClassGetCodes With {.App_Code = "a4", .SystemFlag = True},
New ClassGetCodes With {.App_Code = "a5", .SystemFlag = False}
}
o.GetCodesArray = lstGetCodes.ToArray
Return o
End Function
End Class
Public Class TestWebHttpBehavior
Inherits WebHttpBehavior
Protected Overrides Sub AddServerErrorHandlers(ByVal endpoint As System.ServiceModel.Description.ServiceEndpoint, ByVal endpointDispatcher As System.ServiceModel.Dispatcher.EndpointDispatcher)
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear()
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(New TestErrorHandler)
End Sub
End Class
Public Class TestWcfSvcHostFactory
Inherits ServiceHostFactory
Protected Overrides Function CreateServiceHost(ByVal serviceType As Type, ByVal baseAddresses As Uri()) As ServiceHost
Dim result As New WebServiceHost2(serviceType, True, baseAddresses)
Dim sEnableBasicAuth As String = System.Configuration.ConfigurationManager.AppSettings.Get("EnableBasicAuthentication")
If String.IsNullOrEmpty(sEnableBasicAuth) OrElse String.Compare(sEnableBasicAuth, "false", True) <> 0 Then
result.Interceptors.Add(New TestRequestInterceptor(System.Web.Security.Membership.Provider, "Personify Authentication"))
End If
result.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.None
Dim bahavior As New TestWebHttpBehavior With {.AutomaticFormatSelectionEnabled = True}
result.Description.Endpoints(0).Behaviors.Add(bahavior)
Return result
End Function
End Class
Public Class TestRequestInterceptor
Inherits RequestInterceptor
Private m_provider As MembershipProvider
Private m_realm As String
Public Sub New(ByVal provider As MembershipProvider, ByVal realm As String)
MyBase.New(False)
Me.m_provider = provider
Me.m_realm = realm
End Sub
Protected ReadOnly Property Realm() As String
Get
Return m_realm
End Get
End Property
Protected ReadOnly Property Provider() As MembershipProvider
Get
Return m_provider
End Get
End Property
Public Overrides Sub ProcessRequest(ByRef requestContext As RequestContext)
Dim credentials As String() = ExtractCredentials(requestContext.RequestMessage)
If credentials.Length > 0 AndAlso AuthenticateUser(credentials(0), credentials(1)) Then
InitializeSecurityContext(requestContext.RequestMessage, credentials(0))
Else
Dim reply As Message = Message.CreateMessage(MessageVersion.None, Nothing)
Dim responseProperty As New HttpResponseMessageProperty() With {.StatusCode = HttpStatusCode.Unauthorized}
responseProperty.Headers.Add("WWW-Authenticate", String.Format("Basic realm=""{0}""", Realm))
reply.Properties(HttpResponseMessageProperty.Name) = responseProperty
requestContext.Reply(reply)
requestContext = Nothing
End If
End Sub
Private Function AuthenticateUser(ByVal username As String, ByVal password As String) As Boolean
If Provider.ValidateUser(username, password) Then
Return True
End If
Return False
End Function
Private Function ExtractCredentials(ByVal requestMessage As Message) As String()
Dim request As HttpRequestMessageProperty = DirectCast(requestMessage.Properties(HttpRequestMessageProperty.Name), HttpRequestMessageProperty)
Dim authHeader As String = request.Headers("Authorization")
If authHeader IsNot Nothing AndAlso authHeader.StartsWith("Basic") Then
Dim encodedUserPass As String = authHeader.Substring(6).Trim()
Dim encoding__1 As Encoding = Encoding.GetEncoding("iso-8859-1")
Dim userPass As String = encoding__1.GetString(Convert.FromBase64String(encodedUserPass))
Dim separator As Integer = userPass.IndexOf(":"c)
Dim credentials As String() = New String(1) {}
credentials(0) = userPass.Substring(0, separator)
credentials(1) = userPass.Substring(separator + 1)
Return credentials
End If
Return New String() {}
End Function
Private Sub InitializeSecurityContext(ByVal request As Message, ByVal username As String)
Dim principal As New GenericPrincipal(New GenericIdentity(username), New String() {})
Dim policies As New List(Of IAuthorizationPolicy)()
policies.Add(New PrincipalAuthorizationPolicy(principal))
Dim securityContext As New ServiceSecurityContext(policies.AsReadOnly())
If request.Properties.Security IsNot Nothing Then
request.Properties.Security.ServiceSecurityContext = securityContext
Else
request.Properties.Security = New SecurityMessageProperty() With { _
.ServiceSecurityContext = securityContext _
}
End If
End Sub
Private Class PrincipalAuthorizationPolicy
Implements IAuthorizationPolicy
Private m_id As String = Guid.NewGuid().ToString()
Private user As IPrincipal
Public Sub New(ByVal user As IPrincipal)
Me.user = user
End Sub
Public ReadOnly Property Id As String Implements System.IdentityModel.Policy.IAuthorizationComponent.Id
Get
Return Me.m_id
End Get
End Property
Public Function Evaluate(ByVal evaluationContext As System.IdentityModel.Policy.EvaluationContext, ByRef state As Object) As Boolean Implements System.IdentityModel.Policy.IAuthorizationPolicy.Evaluate
evaluationContext.AddClaimSet(Me, New DefaultClaimSet(Claim.CreateNameClaim(user.Identity.Name)))
evaluationContext.Properties("Identities") = New List(Of IIdentity)(New IIdentity() {user.Identity})
evaluationContext.Properties("Principal") = user
Return True
End Function
Public ReadOnly Property Issuer As System.IdentityModel.Claims.ClaimSet Implements System.IdentityModel.Policy.IAuthorizationPolicy.Issuer
Get
Return ClaimSet.System
End Get
End Property
End Class
End Class
The config is here:
<system.serviceModel>
<services>
<service behaviorConfiguration="TestWcfServiceBehavior"
name="TestServiceLib.TestSvc">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="EPrestBehavior"
name="EPrest" contract="TestServiceLib.ITestSvc" />
<endpoint address="mex" binding="mexHttpBinding" name="EPmex"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="EPrestBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="TestWcfServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I Had a similar issue,
I found that if i navigated to an actual resource it was fine.
for example
http://localhost/tempservicehost/tempservice.svc/test/
assuming you have the following method as well
[OperationContract]
[WebGet(UriTemplate = "/test/")]
public Test TestMethod()
{
return new Test("Hello world");
}
what has happened here is that the standard 404 error that is normally returned has not been rendered the way you are expecting it to. (usually you get a blue header and a line saying service end point or similar)
If you want to customise your errors there is a question Custom Error Handling message for Custom WebServiceHost
That explains how to pick up error codes on the way through and modify the return.
I have a simple class that I trying to populate from an XML document.
The XML file has an attribute called TrackingID in the root node which I would like to get as a property. For some reason, when I deseralize the class, the TrackingID is null. Everything else populates fine. I have tried various attributes on the TrackingID property with no luck.
Any ideas?
Code:
Dim faultXML As String = "<?xml version='1.0' encoding='UTF-8' ?>"
faultXML += "<myxmlns:Fault xmlns:myxmlns='http://somename/space' xmlns:myxmlns_base=http://somename/base' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://somename/space
faultXML += "myxmlns_102809.xsd http://idealliance.org/maildat/Specs/md091/myxmlns70C/base myxmlns_base_102809.xsd' myxmlns:TrackingID='160217057912'>"
faultXML += "<myxmlns:FaultCode>500</myxmlns:FaultCode>"
faultXML += "<myxmlns:FaultDescription>Some Description.</myxmlns:FaultDescription>"
faultXML += "</myxmlns:Fault>"
Dim fault As WebServiceFault
Dim Serializer As New XmlSerializer(GetType(WebServiceFault))
Using sr As New System.IO.StringReader(faultXML)
fault = DirectCast(Serializer.Deserialize(sr), WebServiceFault)
End Using
Class:
Imports System.Xml.Serialization
<System.SerializableAttribute(), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True, [Namespace]:="http://somename/space"), _
System.Xml.Serialization.XmlRootAttribute([ElementName]:="Fault", [Namespace]:="http://somename/space", IsNullable:=False)> _
Public Class WebServiceFault
Private faultCodeField As String
Private faultDescriptionField As String
Private trackingIDField As String
Public Property FaultCode() As String
Get
Return Me.faultCodeField
End Get
Set(ByVal value As String)
Me.faultCodeField = value
End Set
End Property
Public Property FaultDescription() As String
Get
Return Me.faultDescriptionField
End Get
Set(ByVal value As String)
Me.faultDescriptionField = value
End Set
End Property
Public Property TrackingID() As String
Get
Return Me.trackingIDField
End Get
Set(ByVal value As String)
Me.trackingIDField = value
End Set
End Property
End Class
I was able to find an answer. Adding the below attribute solved my problem.
<System.Xml.Serialization.XmlAttributeAttribute(Form:=System.Xml.Schema.XmlSchemaForm.Qualified)> _
Public Property TrackingID() As String
Get
Return Me.trackingIDField
End Get
Set(ByVal value As String)
Me.trackingIDField = value
End Set
End Property