I have a generated XDocument that needs to be validated to Xbrl xsd's
I have created a custom XmlResolver to load all the xsd files from the external party.
This is the GetEntity Function from my resolver so i can get the included xsd's:
Public Overrides Function GetEntity(absoluteUri As Uri, role As String, ofObjectToReturn As Type) As Object
'If absoluteUri.ToString.Contains("www.xbrl.org") Then
' Nothing here yet
'End If
Dim nmSpace As String = _assembly.GetName.Name.ToString
Dim resource = String.Concat(nmSpace, ".", Path.GetFileName(absoluteUri.ToString()))
Dim result = _assembly.GetManifestResourceStream(resource)
Return result
End Function
However there are a lot of xsd's from the xbrl namespace and they don't get loaded.
I started downloading them to include them as a resource but there are just to many files so it doesn't seem like the best solution.
I hope anyone has some experience in validating an Xbrl file because i feel like i'm missing the point here :)
www.Arelle.org
This open source project contains a web-service that can be used to validate Xbrl files.
This what i implemented right now and it checks against all the required Xbrl rules
I'm using plain Xml-Xsd validation and this seems ok so far.
I implemented the custom resolver like this:
Public Class ResourceXmlResolver
Inherits XmlResolver
Private Shared _xmlUrlResolver As XmlUrlResolver = New XmlUrlResolver()
Private _assembly As Assembly
Public Sub New(assembly As Assembly)
_assembly = assembly
End Sub
Public Overrides Function GetEntity(absoluteUri As Uri, role As String, ofObjectToReturn As Type) As Object
If absoluteUri.ToString.Contains("www.xbrl.org") Then
Return _xmlUrlResolver.GetEntity(absoluteUri, role, ofObjectToReturn)
End If
Dim nmSpace As String = _assembly.GetName.Name.ToString
Dim resource = String.Concat(nmSpace, ".", Path.GetFileName(absoluteUri.ToString()))
Dim result = _assembly.GetManifestResourceStream(resource)
Return result
End Function
Public Overrides WriteOnly Property Credentials() As System.Net.ICredentials
Set(value As System.Net.ICredentials)
Throw New NotImplementedException()
End Set
End Property
End Class
The Xsd files provided by the third party are embedded resources.
I set the Assembly to the assembly containing my Xsd files, so when the GetEntity method is called by setting the resolver:
Dim schemas As XmlSchemaSet = New XmlSchemaSet()
schemas.XmlResolver = New ResourceXmlResolver(System.Reflection.Assembly.GetExecutingAssembly)
They are loaded correctly. I do however provide a check for the xsd's from www.xbrl.org.
In that case i'm using the standard XmlUrlResolver to get them from the web.
I also got this working by just downloading all the xbrl xsd's and also embedding them.
I hope this is enough validation for Xbrl but got this working so far :)
Related
I'm working on a series of methods that will test a given path to determine if it is (or, at least could be) valid. I have a couple of overloads that will accept either an IO.FileInfo object or an IO.DirectoryInfo object - which I'd personally prefer to use to help in catching invalid characters as soon as possible in the process. One piece of information I "need" to get as a part of the process is basically the original value the user presented - especially in the case of an IO.FileInfo or IO.DirectoryInfo object as those will automatically prepend the Environment.CurrentDirectory value to any string it determines to be a relative path.
For example:
Dim TestFile As New IO.FileInfo("Testing\This is a test")
Instantiates an IO.FileInfo object with the following properties (among others):
DirectoryName - "C:\Development\My Solution\My Project\bin\Debug\Testing"
Exists - False
Extension - ""
FullName - "C:\Development\My Solution\My Project\bin\Debug\Testing\This is a test"
Name - "This is a test"
OriginalPath - "Testing\This is a test"
This last property is the one I'm most interested in. It's a Protected property of the IO.FileInfo class, which is inherited from the IO.FileSystemInfo class, but it seems to be the best possible way to retrieve the original value passed to the IO.FileInfo constructor. Obviously, I can't access the property directly with a simple Dim TestPath As String = TestFile.OriginalPath - the IDE gives shows the error "'System.IO.FileSystemInfo.OriginalPath' is not accessible in this context because it is 'Protected'" - so I can only think of one way to get this specific piece of information: Create a whole new class that inherits IO.FileSystemInfo with a Public property for the OriginalPath that reads from the base class.
PLEASE NOTE: I do have an overloading method that accepts a String value, but I was actually thinking of trying to "hide" that one behind a Private modifier so that only FileInfo and DirectoryInfo objects could be used to call this method. My primary reasoning there is that, if a FileInfo or DirectoryInfo object fails to instantiate due to invalid characters in the string (or any other reason), there's no reason for me to make the call to this method and I may be able to "clean up" the code a little.
Regardless, the creation of a whole separate class that's really only going to be used to access this one property in this one specific scenario seems like an awful lot of overhead for what should (or, at least could) be a fairly simple thing. Unfortunately, I can't think of any other way to extract that information and I'm just wondering if I may be over-thinking this.
In the meantime, I've gone ahead and created a TempFileInfo class for testing (NOTE: I haven't actually tested it yet) without explicitly implementing any "custom" code for any of the regular Public properties (required when inheriting from the IO.FileSystemInfo class):
Private Class TempFileInfo
Inherits IO.FileSystemInfo
Public Overrides ReadOnly Property Name As String
Get
Throw New NotImplementedException()
End Get
End Property
Public Overrides ReadOnly Property Exists As Boolean
Get
Throw New NotImplementedException()
End Get
End Property
Public Overrides Sub Delete()
Throw New NotImplementedException()
End Sub
Public Shadows ReadOnly Property OriginalPath As String
Get
Return MyBase.OriginalPath
End Get
End Property
Public Shared Widening Operator CType(v As FileInfo) As TempFileInfo
Dim FSI As FileSystemInfo = v
Return CType(FSI, TempFileInfo)
End Operator
End Class
You'll note that I also included a Widening Operator that should allow me to convert from a "regular" IO.FileInfo object to my TempFileInfo object so that I can access my "custom" OriginalPath property. This is the only way I've found so far to "get there from here", but I wanted to go ahead and ask here in case there are other suggestions or things I might be overlooking.
The only "saving grace" for this method of implementation is that, because the "custom" TempFileInfo, the standard IO.FileInfo, and the standard IO.DirectoryInfo classes all inherit from the IO.FileSystemInfo class, I should be able to simply create an overloaded Widening Operator method for converting both IO.FileInfo objects as well as IO.DirectoryInfo objects instead of having to create a separate TempDirInfo class.
The path entered when a FileInfo or DirectoryInfo object is created is stored in the protected String OriginalPath field - which is used for serialization purposes - and the internal DisplayPath property, which is used as an internal reference.
When the class object is initialized (see the Init() method in the .Net source code), the path entered is stored in both the OriginalPath Field and the DisplayPath Property.
Both classes don't provide a public property to retrieve the initial path used to create the object.
They both, instead, return the DisplayPath property value as an override to the ToString() method:
Dim fInfo = New FileInfo("\SomePath\SomeFileName.ext")
Dim originalPath = fInfo.ToString()
var fInfo = new FileInfo(#"\SomePath\SomeFileName.ext");
string originalPath = fInfo.ToString();
I'm writing some vb.net code to retrieve some data from middleware, do some stuff with it, and then save a dictionary of name/value pairs to cache for quick retrieval when needed.
It all seems to go well until I retrieve the object from cache and it is always Null/Nothing.
Yet in the watch window I can see my cached object and it has data in it.
Thinking maybe it's a serialization issue I made a new class that inherits Dictionary and is marked as serializable but I still get the same results.
So right now I have this class:
<Serializable()> Public Class SerialDict
Inherits Dictionary(Of String, String)
Public Sub New()
End Sub
End Class
I populate it and put it into cache like this:
Dim Licenses As New SerialDict
For Each r As DataRow In dtLicenses.Rows
Dim prikey As String = r("SettingID").ToString.Trim
Dim decryptionKey As String = GetHash((xx))
Dim licData As String = DecryptData(r("SettingVal"), decryptionKey)
Licenses.Add(r("SettingKey"), licData)
Next
If IsNothing(HttpContext.Current.Cache("Licenses")) Then
HttpContext.Current.Cache.Add("Licences", Licenses, Nothing, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Default, Nothing)
End If
Then elsewhere we need to check that data so I try to retrieve it like this:
Dim Licences As SerialDict = CType(HttpContext.Current.Cache("Licenses"), SerialDict)
At this point Licenses is always Nothing, but the watch window shows data in HttpContext.Current.Cache("Licenses").
Any suggestions? Thanks!
I would appreciate if somebody could answer some questions regarding storing and searching object collections please. If you could give a basic example of any suggestions I would be very grateful.
Storing:
I'm writing an application which needs to search Active Directory for computer objects, and I'm storing them in a collection of objects. I want to save the computer objects collection along with additional information which is not stored in Active Directory (e.g. the computer's MAC address) for the next time the application is run. I also want to save a list of OU's.
Here is my object collection so far (It will have more properties). What is the best method of saving the collection? Preferably not using a database or will saving to a file have a drastic performance impact?
Or is there a better way to do what I have below?
Public Class Computer
Public Property Name As String
Public Property FQDN As String
Public Property Path As String
End Class
Public Class ComputerCollection
Inherits Collections.CollectionBase
Public Sub Add(ByVal computer As Computer) 'Adds a new computer object to the collection
List.Add(computer)
End Sub
End Class
Searching:
I have a layout similar to ADUC with a tree view of OU's and a list view displaying computer objects in the selected OU. The following code loops through the computer object collection checking if the path of the computer object matches the selected OU path and then displays them in the list view.
Is this the best method in terms of performance? or is there a faster way?
Private Sub tvOU_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles tvOU.AfterSelect
lvComputers.Items.Clear()
If tvOU.SelectedNode.Name > "" Then
For Each computerObj In computers
If computerObj.Path.ToString.Replace("CN=" + computerObj.Name + ",", "") = tvOU.SelectedNode.Name Then
Dim lvItem As New ListViewItem
lvItem.Text = computerObj.Name
lvComputers.Items.Add(lvItem)
End If
Next
Else
Exit Sub
End If
End Sub
A simple List(Of Computer) is indeed all you need unless there is some other unknown requirement. Saving is very simple using serialization for this type of thing, and would work the same for a List or Collection<T>.
Imports System.Collections.ObjectModel
Public Class ComputersCollection
Inherits Collection(Of Computer)
' NOT the crude thing in the VB NameSpace
' there is almost nothing to add: item, add and remove
' are in the base class
' ... perhaps saving and retrieving them by a key (name)
' which may do away with the search procedure in the posted code
End Class
Private Computers As New Collection(Of Computer)
' or
Private Computers As New List(Of Computer)
The other part, saving your collection, can be simple with serialization. First, you will have to add the Serializable attribute to your Computer class:
<Serializable>
Public Class Computer
If you forget, you get the error Class foobar is not marked as serializable. Save to disk:
Imports System.Runtime.Serialization
Private myComputerFile As String = ...
Dim bf As New BinaryFormatter
Using fs As New FileStream(myComputerFile , FileMode.OpenOrCreate)
bf.Serialize(fs, Computers)
End Using
Then you can recreate the List or Collection just as easily; this time the List:
' ToDo: add a check to skip if file is not there
' as in the first time run
Dim bf As New BinaryFormatter
Using fs As New FileStream(myComputerFile , FileMode.Open)
Computers = CType(bf.Deserialize(fs), List(Of Computers))
End Using
Alternatively you can use the XML serializer to create an XML File or use the faster, smarter binary serializer is ProtoBuf-Net
within webservce MyService.
DocumentList Class containing properties id, name -- Class is Serializable
Public Function getDocList(args...) as List(Of DocumentList)
'code to add to documentlist
'no issue here...
End Function
Within project.
Dim thisService as New MyService
Sub Main
Dim docList as New List(of DocumentList)
docList = thisService.getDocList(args...)
End Sub
I get error - cannot convert -1 dimensional array to generic list of DocumentList.
If I consume DocumentList within the service, no issues. I can iterate with for each. But, within the project, which calls the service, I cannot consume DocumentList.
I have set the service to pass a string, and this is possible. Only the List(Of DocumentList) is an issue.I think I may need reflection, or a proper understanding of collections. Not sure.
Thank you.
Dim docList as DocumentList()
Cannot return a complex type, had to set my DocumentList as an array in the project calling the webservice.
http://www.asquestion.com/question/60333227137608045/Problem-returning-a-collection-from-a-web-service
So, I am very new to creating web services, but have successfully managed to make a simple webservice which returns information as I'd need from a database as List(Of dictionary(of string, string)) object.
For the purpose of testing, I have created this manually, my code looks like this:
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Web.Script.Serialization
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class test
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function dic() As String
Dim newDic As New List(Of Dictionary(Of String, String))
Dim one As New Dictionary(Of String, String)
one.Add("id", "1")
one.Add("name", "the name")
one.Add("price", "5.99")
newDic.Add(one)
Dim two As New Dictionary(Of String, String)
two.Add("id", "2")
two.Add("name", "item name two")
two.Add("price", "1299")
newDic.Add(two)
Dim s As New JavaScriptSerializer
Dim str As String = s.Serialize(newDic)
Return str
End Function
End Class
This webservice "dic" gives me serialized string/list looking like this:
[{"id":"1","name":"the name","price":"5.99"},{"id":"2","name":"item name two","price":"1299"}]
I can read this in VB code like this:
Sub loadMe() Handles Me.Load
Dim t As New websvce.testSoapClient
Dim d As String = t.dic
Dim s As New JavaScriptSerializer
Dim d2 = s.DeserializeObject(d)
Response.Write(d2(1)("name") & "<hr>")
End Sub
which gives me the output of the "name" element with index "1". It works fine.
However, unsurprisingly, it does not work when trying to grab this info with jQuery using code as follows:
$(document).ready(function () {
$.getJSON('URL/test.asmx/dic', function (data) {
alert(data);
});
});
So I have spent a good part of the day Googling this, and found all kinds of comments and conversations telling me about why cross domain scripting is not allowed and that there are ways round it using Proxies, adding headers to pages and so on... but... no conclusive solution to the problem.
Here's some of the SO questions I have found:
Origin http://localhost is not allowed by Access-Control-Allow-Origin
How to implement "Access-Control-Allow-Origin" header in asp.net
There's many more, but I cannot find an absolute solution, which fits my criteria. I want to output data in a format similar to that above, and access it from another domain with jQuery.
The easiest work around I have found is to write a handling page which runs on the receiving server, simply loading the data as per my VB code example above and operating as a webMethod on that server to spit out JSON, but I'd rather the whole thing could be handling by the web service, thus no need to run extra files on the consuming server.
EDIT; actually, I do also need to be able to perform POST operations.