F# Using XMLProvider in PCL Project - f#

I created a new VS2015 F# PCL Project targeting 4.5.1. I added in FSharp.Data and got the XML type provider to pull down the data:
#r "..\packages\FSharp.Data.2.2.5\lib\portable-net40+sl5+wp8+win8\FSharp.Data.dll"
open System.IO
open FSharp.Data
let baseDirectory = __SOURCE_DIRECTORY__
let baseDirectory' = Directory.GetParent(baseDirectory)
type Campaign = XmlProvider<"../Data/Campaign.xml">
let filePath = "Data\Campaign.xml"
let fullPath = Path.Combine(baseDirectory'.FullName, filePath)
let campaignText = File.ReadAllText(fullPath)
let campaigns = Campaign.Parse(campaignText)
When I try and dot the result, it is telling me that I need to add a reference to System.Xml.Linq. However, I can't add that library to a PCL project. Is there a way I can parse the data?

Just add the reference to System.Xml.Linq in your script file like so:
#r "packages\FSharp.Data.2.2.5\lib\portable-net40+sl5+wp8+win8\FSharp.Data.dll"
#r "System.Xml.Linq"

Related

Using ConfigurationManger in F# project

I am simply trying to use the ConfigurationManager within an F# project but I am getting the error:
This value is not a function and cannot be applied
here is the code:
open System.Configuration
let connectionString = ConfigurationManager.ConnectionStrings["ManagementDb"].ConnectionString
I have also referenced the System.Configuration library.
I haven't verified this in Visual Studio, but usually there is a dot ('.') when using an F# index.
i.e.
let connectionString = ConfigurationManager.ConnectionStrings.["ManagementDb"].ConnectionString

Referencing external assembly fails

I can't get referencing a private assembly working. I've followed the documentation, but it still fails with the error message:
2016-09-29T19:43:08.615 startup(2,1): error FS82: Could not resolve this reference. Could not locate the assembly "Backend.dll". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. (Code=MSB3245)
Here is the run.fsx file:
#r "Backend.dll"
open System
open System.IO
open System.Net
open System.Net.Http.Headers
open System.Collections.Generic
open CoP
let createResponse json =
let responseJson = Request.handleJson json
let response = new HttpResponseMessage()
response.Content <- new StringContent(responseJson)
response.StatusCode <- HttpStatusCode.OK
response.Content.Headers.ContentType <- MediaTypeHeaderValue("application/json")
response
let Run (req: HttpRequestMessage) =
async {
let! json = req.Content.ReadAsStringAsync()
return createResponse json
} |> Async.StartAsTask
I've also placed the Backend.dll in a bin folder inside the same folder as the function.
What am I missing?
Looks like you ran into a bug with private assembly resolution in the Azure Functions F# implementation.
I've opened this issue for tracking and will have a fix included in the next release:
https://github.com/Azure/azure-webjobs-sdk-script/issues/733
In the meantime, you should be able to reference your private assembly by using:
#r "bin/Backend.dll"
Hope this helps!
If that was a question about .fsx scripts alone, I'd say you're missing the part where you tell FSI where to look for the dll to reference:
#I "bin"
#r "BackEnd.dll"
Is there anything Azure does to put the .\bin folder within the context reachable by #r directive?

F# interactive window folder and type provider default folder

I already changed the folder to my project folder. F# interactive:how to display/change current working directory
However, it got the following error when I sent let xml = XmlProvider<"./DbToken.xml">.GetSample() to interactive window.
DbShared.fs(66,11): error FS3033: The type provider 'ProviderImplementation.XmlProvider' reported an error: Cannot read sample XML from './DbToken.xml': Could not find file 'C:\Users\a\AppData\Local\Temp\DbToken.xml'.
You can set Environment.CurrentDirectory as in the comment but you can also specify the path to the xml file:
[<Literal>]
let xmlpath = __SOURCE_DIRECTORY__ + "/test.xml"
And then say: let xml = XmlProvider<xmlpath>.GetSample()

F# Module/Namespace Error

My first program with F#.
I have one file like so:
namespace LanguageMapper.Data
#if INTERACTIVE
#r "System.Data"
#r "System.Data.Linq"
#r "FSharp.Data.TypeProviders"
#endif
open System.Data
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders
module Data =
// You can use Server Explorer to build your ConnectionString.
type SqlConnection = Microsoft.FSharp.Data.TypeProviders.SqlDataConnection<ConnectionString = #"connstring">
let db = SqlConnection.GetDataContext()
Then i have another file like so
namespace LanguageMapper.Program
open Data
module Program =
[<EntryPoint>]
let main argv =
let getLocale x =
match x with
| [|"live"|] -> "live"
| [|"dev"|] -> "dev"
| _ -> "local"
Over top of the open Data i get a red squiggly in VS telling me:
"Error 1 This declaration opens the namespace or module
'Microsoft.FSharp.Data' through a partially qualified path. Adjust
this code to use the full path of the namespace. This change will make
your code more robust as new constructs are added to the F# and CLI
libraries."
What am i doing wrong? I just want to reference one file from the other.
You need to open the module using its fully qualified name, that is including its namespace. So in LanguageMapper.Program you need to open LanguageMapper.Data.Data (only the last bit is the module name).
The Compiler is complaining on your open definition because it only specifies to open a namespace or module named Data - and it finds one in Microsoft.FSharp.Data, probably because there are some 'automatic' opens for the Microsoft.FSharp namespaces.

control file structure of a zip archive in FSharp

the following is a code sample that takes a list of file names and zips them into a single archive. The problem I'm having is that I'd like for the file described by filname be in the top level of the zip archive (i.e. when the archive is opened, "clientName....xml" is the first thing you see, instead of the folder "XML").
let filename = sprintf "C:\\XML\\ClientName_%s.xml" (System.DateTime.Now.ToString("ddMMyyyy"))
use fs = new FileStream(filename, FileMode.Create)
let xmlSerializer = XmlSerializer(typeof<log>)
xmlSerializer.Serialize(fs,logObj)
fs.Close()
use zipfile = new ZipFile()
let basePath = path.Replace("/", "\\")
for fileObj in files do
let relativeFilePath = basePath + (fileObj.Filename).Replace("/", "\\")
printfn "%s" relativeFilePath
zipfile.AddFile(relativeFilePath) |> ignore
()
zipfile.AddFile(filename) |> ignore
let zipFileName = sprintf "C:\\XML\\Compliance_%s.zip" (System.DateTime.Now.ToString("ddMMyyyy"))
zipfile.Save(zipFileName)
Where does the ZipFile type come from? I don't think this is a standard .NET class... I tried searching and found this library http://dotnetzip.codeplex.com/ which has a class matching to your sample :-)
The mentioned library also has AddFile overload that takes two string - the source file name and a relative file name in the ZIP file. This seems exactly like what you're looking for. I guess the call would be something like zipfile.AddFile(absolutePath, "/")...

Resources