{"id":31156625,"url":"https://github.com/fuzzzerd/fmdata","last_synced_at":"2025-09-18T21:04:09.614Z","repository":{"id":31455875,"uuid":"126491080","full_name":"fuzzzerd/fmdata","owner":"fuzzzerd","description":"A simple and flexible FileMaker Data API Client for .NET. Use FMData to integrate your FileMaker data into .NET websites and applications.","archived":false,"fork":false,"pushed_at":"2025-08-12T22:12:52.000Z","size":1453,"stargazers_count":31,"open_issues_count":6,"forks_count":12,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-08-13T00:13:00.637Z","etag":null,"topics":["c-sharp","data-api","dotnet-core","filemaker","filemaker-api","filemaker-data-api","filemaker-integration","json","xml"],"latest_commit_sha":null,"homepage":"https://fmdata.io","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fuzzzerd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["fuzzzerd"]}},"created_at":"2018-03-23T13:45:20.000Z","updated_at":"2025-08-12T22:12:56.000Z","dependencies_parsed_at":"2023-01-14T19:04:45.336Z","dependency_job_id":"48cab416-d0de-4a1e-9a80-a74a8fc963cc","html_url":"https://github.com/fuzzzerd/fmdata","commit_stats":null,"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/fuzzzerd/fmdata","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuzzzerd%2Ffmdata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuzzzerd%2Ffmdata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuzzzerd%2Ffmdata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuzzzerd%2Ffmdata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fuzzzerd","download_url":"https://codeload.github.com/fuzzzerd/fmdata/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuzzzerd%2Ffmdata/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275416179,"owners_count":25460913,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-16T02:00:10.229Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-sharp","data-api","dotnet-core","filemaker","filemaker-api","filemaker-data-api","filemaker-integration","json","xml"],"created_at":"2025-09-18T21:03:50.617Z","updated_at":"2025-09-18T21:04:09.587Z","avatar_url":"https://github.com/fuzzzerd.png","language":"C#","funding_links":["https://github.com/sponsors/fuzzzerd"],"categories":[],"sub_categories":[],"readme":"# FMData\n\n[![fmdata logo, a C# client for FileMaker](https://raw.githubusercontent.com/fuzzzerd/fmdata/master/images/color-cropped.png)](https://github.com/fuzzzerd/fmdata)\n\n## Packages\n\n| Package | Build Status | MyGet | Nuget |\n|---|---|---|---|\n| FMData | [![.NET CI Build](https://github.com/fuzzzerd/fmdata/actions/workflows/dotnet.yml/badge.svg)](https://github.com/fuzzzerd/fmdata/actions/workflows/dotnet.yml)| [![Myget](https://img.shields.io/myget/filemaker/vpre/FMData.svg)](https://www.myget.org/feed/filemaker/package/nuget/FMData) | [![NuGet](https://img.shields.io/nuget/v/FMData?style=flat\u0026label=NuGet)](https://www.nuget.org/packages/FMData/) |\n| FMData.Rest | [![.NET CI Build](https://github.com/fuzzzerd/fmdata/actions/workflows/dotnet.yml/badge.svg)](https://github.com/fuzzzerd/fmdata/actions/workflows/dotnet.yml) | [![MyGet Pre Release](https://img.shields.io/myget/filemaker/vpre/FMData.Rest.svg)](https://www.myget.org/feed/filemaker/package/nuget/FMData.Rest) | [![NuGet](https://img.shields.io/nuget/v/fmdata.rest?style=flat\u0026label=NuGet)](https://www.nuget.org/packages/FMData.Rest/) |\n| FMData.Rest.Auth.FileMakerCloud  | [![.NET CI Build](https://github.com/fuzzzerd/fmdata/actions/workflows/dotnet.yml/badge.svg)](https://github.com/fuzzzerd/fmdata/actions/workflows/dotnet.yml) | [![FMData.Rest.Auth.FileMakerCloud](https://img.shields.io/myget/filemaker/vpre/FMData.Rest.Auth.FileMakerCloud.svg)](https://www.myget.org/feed/filemaker/package/nuget/FMData.Rest.Auth.FileMakerCloud) | [![NuGet](https://img.shields.io/nuget/v/fmdata.rest.auth.filemakercloud?style=flat\u0026label=NuGet)](https://www.nuget.org/packages/FMData.Rest.Auth.FileMakerCloud/) |\n| FMData.Xml  | [![.NET CI Build](https://github.com/fuzzzerd/fmdata/actions/workflows/dotnet.yml/badge.svg)](https://github.com/fuzzzerd/fmdata/actions/workflows/dotnet.yml) | [![FMData.Xml](https://img.shields.io/myget/filemaker/vpre/FMData.Xml.svg)](https://www.myget.org/feed/filemaker/package/nuget/FMData.Xml/) | [![NuGet](https://img.shields.io/nuget/v/fmdata.xml?style=flat\u0026label=NuGet)](https://www.nuget.org/packages/FMData.Xml/) |\n\nThere are plenty of ways to consume RESTful APIs from .NET, but the goal of this project is to provide a blended FileMaker-idiomatic and .NET-idiomatic experience for developers consuming data from FileMaker databases in .NET applications.\n\nThe project is organized as three main packages, with a child Auth package for FileMaker Cloud:\n\n- `FMData` is the core and it contains the base and abstract classes utilized by the other implementations.\n- `FMData.Rest` is for the Data API and\n  - `FMData.Rest.Auth.FileMakerCloud` is used for authentication to the Data API hosted by FileMaker Cloud\n- `FMData.Xml` is for consuming the legacy Xml/CWP API.\n\n\u003e *Note: Xml support is experimental, if you need full cwp/xml coverage [check out fmDotNet](https://github.com/fuzzzerd/fmdotnet).*\n\nIf you've found a bug, please submit a bug report. If you have a feature idea, open an issue and consider creating a pull request.\n\n## Repository Information\n\n![NuGet](https://img.shields.io/nuget/dt/FMData?style=flat\u0026label=NuGet)\n\n[![FMData repository/commit activity the past year](https://img.shields.io/github/commit-activity/y/fuzzzerd/fmdata.svg)](https://github.com/fuzzzerd/fmdata/commits/master)\n\n[![FMData issues](https://img.shields.io/github/issues/fuzzzerd/fmdata.svg)](https://github.com/fuzzzerd/fmdata/issues)\n\n[![CodeFactor](https://www.codefactor.io/repository/github/fuzzzerd/fmdata/badge)](https://www.codefactor.io/repository/github/fuzzzerd/fmdata)\n\n[![Code size in bytes](https://img.shields.io/github/languages/code-size/fuzzzerd/fmdata.svg)](https://github.com/fuzzzerd/fmdata/commits/master)\n\n[![Language Count](https://img.shields.io/github/languages/count/fuzzzerd/fmdata.svg)](https://github.com/fuzzzerd/fmdata/commits/master)\n\n[![license](https://img.shields.io/github/license/fuzzzerd/fmdata.svg)](https://github.com/fuzzzerd/fmdata/blob/master/LICENSE)\n\n## Installation\n\nInstall via `dotnet add` or nuget. Stable releases are on NuGet and CI builds are on MyGet.\n\n```ps\ndotnet add package FMData.Rest\n```\n\n## Example Usage\n\nThe recommended way to consume this library is using a strongly typed model as follows.\n\nPlease review the /tests/FMData.Rest.Tests/ project folder for expected usage flows.\n\n### Setting up your model\n\nA model should roughly match a table in your solution. Its accessed via layout.\n\n```csharp\n// use the DataContract attribute to link your model to a layout\n[DataContract(Name=\"NameOfYourLayout\")]\npublic class Model\n{\n    [DataMember]\n    public string Name { get; set; }\n\n    // if your model name does not match use DataMember\n    [DataMember(Name=\"overrideFieldName\")] // the internal database field to use\n    public string Address { get; set; }\n\n    [DataMember]\n    public string SomeContainerField { get; set; }\n\n    // use the ContainerDataFor attribute to map container data to a byte[]\n    [ContainerDataFor(\"SomeContainerField\")] // use the name in your C# model\n    public byte[] DataForSomeContainerField { get; set; }\n\n    // if your model has properties you don't want mapped use\n    [IgnoreDataMember] // to skip mapping of the field\n    public string NotNeededField { get; set; }\n}\n```\n\n### Using IHttpClientFactory\n\nConstructors take an `HttpClient` and you can setup the DI pipeline in Startup.cs like so for standard use:\n\n```csharp\nservices.AddSingleton\u003cFMData.ConnectionInfo\u003e(ci =\u003e new FMData.ConnectionInfo\n{\n    FmsUri = \"https://example.com\",\n    Username = \"user\",\n    Password = \"password\",\n    Database = \"FILE_NAME\"\n});\nservices.AddHttpClient\u003cIFileMakerApiClient, FileMakerRestClient\u003e();\n```\n\nIf you prefer to use a singleton instance of `IFileMakerApiClient` you have to do a little bit more work in startup. This can improve performance if you're making lots of hits to the Data API over a single request to your application:\n\n```csharp\nservices.AddHttpClient(); // setup IHttpClientFactory in the DI container\nservices.AddSingleton\u003cFMData.ConnectionInfo\u003e(ci =\u003e new FMData.ConnectionInfo\n{\n    FmsUri = \"https://example.com\",\n    Username = \"user\",\n    Password = \"password\",\n    Database = \"FILE_NAME\"\n});\n// Keep the FileMaker client as a singleton for speed\nservices.AddSingleton\u003cIFileMakerApiClient, FileMakerRestClient\u003e(s =\u003e {\n    var hcf = s.GetRequiredService\u003cIHttpClientFactory\u003e();\n    var ci = s.GetRequiredService\u003cConnectionInfo\u003e();\n    return new FileMakerRestClient(hcf.CreateClient(), ci);\n});\n```\n\nBehind the scenes, the injected `HttpClient` is kept alive for the lifetime of the FMData client (rest/xml) and reused throughout. This is useful to manage the lifetime of `IFileMakerApiClient` as a singleton, since it stores data about FileMaker Data API tokens and reuses them as much as possible.  Simply using `services.AddHttpClient\u003cIFileMakerApiClient, FileMakerRestClient\u003e();` keeps the lifetime of our similar to that of a 'managed `HttpClient`' which works for simple scenarios.\n\nTest both approaches in your solution and use what works.\n\n### Authentication with FileMaker Cloud\n\nWe can use the `FileMakerRestClient`, when the setup is done. Just create a new `ConnectionInfo` object and set the required properties:\n\n```cs\nvar conn = new ConnectionInfo();\nconn.FmsUri = \"https://{NAME}.account.filemaker-cloud.com\";\nconn.Username = \"user@domain.com\";\nconn.Password = \"********\";\nconn.Database = \"Reporting\";\n```\n\nThen instantiate the `FileMakerRestClient` with a `FileMakerCloudAuthTokenProvider` as follows:\n\n```cs\nvar fm = new FileMakerRestClient(new HttpClient(), new FileMakerCloudAuthTokenProvider(conn));\n```\n\nFor a full description of using FileMaker Data API with FileMaker Cloud, [see this comment](https://github.com/fuzzzerd/fmdata/issues/217#issuecomment-1203202293).\n\n### Performing a Find\n\n```csharp\nvar client = new FileMakerRestClient(\"server\", \"fileName\", \"user\", \"pass\"); // without .fmp12\nvar toFind = new Model { Name = \"someName\" };\nvar results = await client.FindAsync(toFind);\n// results = IEnumerable\u003cModel\u003e matching with Name field matching \"someName\" as a FileMaker FindRequest.\n```\n\n### Create a new record\n\n```csharp\nvar client = new FileMakerRestClient(\"server\", \"fileName\", \"user\", \"pass\"); // without .fmp12\nvar toCreate = new Model { Name = \"someName\", Address = \"123 Main Street\" };\nvar results  = await client.CreateAsync(toCreate);\n//  results is an ICreateResponse which indicates success (0/OK or Failure with FMS code/message)\n```\n\n### Updating a record\n\n```csharp\nvar client = new FileMakerRestClient(\"server\", \"fileName\", \"user\", \"pass\"); // without .fmp12\nvar fileMakerRecordId = 1; // this is the value from the calculation: Get(RecordID)\nvar toUpdate = new Model { Name = \"someName\", Address = \"123 Main Street\" };\nvar results = await client.EditAsync(fileMakerRecordId, toCreate);\n//  results is an IEditResponse which indicates success (0/OK or Failure with FMS code/message)\n```\n\n### Find with FileMaker ID Mapping\n\nNote you need to add an int property to the Model `public int FileMakerRecordId { get; set; }` and provide the Func to the `FindAsync` method to tell FMData how to map the FileMaker ID returned from the API to your model.\n\n```csharp\nFunc\u003cModel, int, object\u003e FMRecordIdMapper = (o, id) =\u003e o.FileMakerRecordId = id;\nvar client = new FileMakerRestClient(\"server\", \"fileName\", \"user\", \"pass\"); // without .fmp12\nvar toFind = new Model { Name = \"someName\" };\nvar results = await client.FindAsync(toFind, FMRecordIdMapper);\n// results is IEnumerable\u003cModel\u003e matching with Name field matching \"someName\" as a FileMaker FindRequest.\n```\n\n### Find with Data Info\n\n```csharp\nvar toFind = new Model { Name = \"someName\" };\nvar req = new FindRequest\u003cModel\u003e() { Layout = layout };\nreq.AddQuery(toFind, false);\nvar (data, info) = await fdc.SendAsync(req, true);\n```\n\nAlternatively, if you create a calculated field `Get(RecordID)` and put it on your layout then map it the normal way.\n\n### Find and load Container Data\n\nMake sure you use the `[ContainerDataFor(\"NameOfContainer\")]` attribute along with a `byte[]` property for processing of your model.\n\n```csharp\nvar client = new FileMakerRestClient(\"server\", \"fileName\", \"user\", \"pass\"); // without .fmp12\nvar toFind = new Model { Name = \"someName\" };\nvar results = await client.FindAsync(toFind);\nawait client.ProcessContainers(results);\n// results = IEnumerable\u003cModel\u003e matching with Name field matching \"someName\" as a FileMaker FindRequest.\n```\n\n### Insert or Update Container Data\n\n```csharp\n// assume recordId = a FileMaker RecordId mapped using FMIdMapper\n// assume containerDataByteArray is a byte array with file contents of some sort\nvar client = new FileMakerRestClient(\"server\", \"fileName\", \"user\", \"pass\"); // without .fmp12\n_client.UpdateContainerAsync(\n    \"layout\",\n    recordId,\n    \"containerFieldName\",\n    \"filename.jpg/png/pdf/etc\",\n    containerDataByteArray);\n```\n\n\u003e *Note: In order to create a record with container data two calls must be made. One that creates the actual record ( see above) and one that updates the container field contents.*\n\n## FileMaker Documentation\n\nLatest Versions\n\n- [FileMaker Data API Documentation (FMS19)](https://help.claris.com/en/data-api-guide/)\n- [FileMaker Server 19 Custom Web Publishing Guide](https://help.claris.com/en/server-custom-web-publishing-guide.pdf)\n\nOlder Versions\n\n- [FileMaker Data API Documentation (FMS18)](https://fmhelp.filemaker.com/docs/18/en/dataapi/)\n- [FileMaker Server 18 Custom Web Publishing Guide](https://fmhelp.filemaker.com/docs/18/en/fms18_cwp_guide.pdf)\n- [FileMaker Data API Documentation (FMS17)](https://fmhelp.filemaker.com/docs/17/en/dataapi/)\n- [FileMaker REST API Documentation (FMS16)](https://fmhelp.filemaker.com/docs/16/en/restapi/) *-- Not Supported by this project.*\n- [FileMaker Server 16 Web Publishing Guide](https://fmhelp.filemaker.com/docs/16/en/fms16_cwp_guide.pdf)\n- [FileMaker Server 15 Web Publishing Guide](https://fmhelp.filemaker.com/docs/15/en/fms15_cwp_guide.pdf)\n\n## Versioning\n\nWe use [Semantic Versioning](http://semver.org/). Using the Major.Minor.Patch syntax, we attempt to follow the basic rules\n\n 1. MAJOR version when you make incompatible API changes,\n 2. MINOR version when you add functionality in a backwards-compatible manner, and\n 3. PATCH version when you make backwards-compatible bugfixes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuzzzerd%2Ffmdata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffuzzzerd%2Ffmdata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuzzzerd%2Ffmdata/lists"}