.NET SDK, v4.1
Main responsibility of FIFA Connect ID Service (FCI) is to generate a unique FIFA_ID for a football/futsal/beach soccer stakeholder. Football Management Systems operating in different Member Associations integrate with the FCI in order to register persons, organisations and facilities, and have FIFA_ID generated for these entities. Integration can be done in two ways: * directly - by using REST API of FCI * [recommended] via SDK, a library which wraps REST API and simplifies access to the service
This documentation is a reference point for a developer who wants to use SDK to integrate Football Management System with FCI.
Documentation is organised into three main chapters which discuss all aspects of a certain entity type management. * Chapter 3 - describes how to register, update or merge the Person. A lot of attention is paid to finding national and international duplicates for a person being registered. * Chapter 4 - discusses all aspects of Organisation registration, update and merge * Chapter 5 - shows how to register or update a Facility
Chapters 2 and 6 provide - respectively - a brief introduction to setting up the integration and an overview of latest changes to SDK.
Class names – although sometimes confusing – follow the FIFA Data Standard and as such they cannot be subject of modification.
Some SDK classes that represent read-only data provided by the server side (e.g. PersonDuplicateType
) contain setter methods. This data isn’t normally modified on the client side. The reason to have them, however, is that the client can easily simulate possible response from service by setting values to objects – and that can be useful for testing.
All SDK methods requires date and time in UTC time zone. If date/time passed as an argument to SDK method and is not in UTC then Exception is thrown. Consequently, all date/time objects returned from the SDK are in UTC.
Note: pay special attention to birth date so they are not affected by time zones changes. For example both person born in Chile and Japan on 1.1.2012 should be registered as born on 1.1.2012 0:00 UTC.
Any instance members are not guaranteed to be thread safe. In particular all methods on FifaConnectServiceBusClient
cannot be called from multiple threads simultaneously. If needed, new instance of FifaConnectServiceBusClient
should be created per thread.
SDK libraries to reference:
Fifa.ConnectId.Sdk.dll
Fifa.ConnectServiceBus.Sdk.dll
Microsoft.Rest.ClientRuntime.dll
Microsoft.IdentityModel.Clients.ActiveDirectory.dll
Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll
Newtonsoft.Json.dll
Current version of the SDK supports two approaches to operations on Person entity:
Two following sections describe implementation steps which are necessary to cover both scenarios: * Chapter 3.1 - Person registration/update/search together with a duplicate check * Chapter 3.2 - operations on Person entity not requiring a duplicate check
The RegistrationFacade
class simplifies the usage of FifaConnectIdClient
and FifaConnectServiceBusClient
, in order to cover full scenario of registering a person in FIFA Connect ID. If potential duplicates are found, Registration Facade will send requests for person details to other MAs using Connect Service Bus and wait for their response (with timeout). The same logic needs to apply when one tries to update Person details or search for duplicates but does not intend to register a person even if no duplicates are found.
In order to start registering entities (persons, facilities, organisations), you will need a FIFA identifier of your organisation (i.e. MA), a set of client credentials and pair of public and private certificates generated. Instruction of how to generate and upload certificate can be found in fifa-connectservicebus-certificates-generation.html
. Instruction of how to create and use the 'IPrivateKeyStorage' can be found in fifa-connectservicebus-sdk-net-2.1.html
, chapter 2.1.1 - Setup private certificate.
Then create RegistrationFacade
object:
var environment = ConnectIdEnvironment.Beta;
var clientCredentials = new ClientCredentials("clientId", "secretKey");
var privateKeyStorage = new YourPrivateKeyStorage();
var facade = new RegistrationFacade(environment, clientCredentials, privateKeyStorage);
After creating facade, you can set up the background listener, which will listen and process new messages received from Connect Service Bus.
When BackgroundListener
receives a message with a request for person's details it will call a method GetPersonDetails
on PersonDetailsProvider
passing FIFA ID of a person. Therefore you have to provide implementation of IPersonDetailsProvider
that makes a lookup (e.g. in your database) and returns a valid PersonLocal
XML from FIFA Data Standard ([http://data.fifaconnect.org]). If for any reason record for a requested person is not found or cannot be retured, PersonDetailsProvider
should return null
or empty string.
Code snippet below shows how to provide sample PersonDetailsProvider.
var provider = new YourPersonDetailsProvider();
var listener = facade.ConfigureListener(provider);
// start listening for new messages
await listener.RunWithTimeout(TimeSpan.FromMinutes(10)).ConfigureAwait(false);
XML below is an example of data that should be returned by PersonDetailsProvider
<?xml version="1.0" encoding="UTF-8"?>
<PersonLocal PersonFIFAId="105C3Z1" LocalFirstName="ΑΓΓΕΛΗΣ" LocalLastName="ΧΑΡΑΛΑΜΠΟΥΣ" LocalLanguage="gre" LocalCountry="CY" LocalSystemMAId="1234567" InternationalFirstName="ANGELIS" InternationalLastName="CHARALAMBOUS" Gender="male" DateOfBirth="1989-05-31" PlaceOfBirth="Larnaca" RegionOfBirth="Larnaca" CountryOfBirth="CY" Nationality="CY">
<NationalIdentifier Identifier="GHKJKLD123132132" NationalIdentifierNature="PassportNumber" Country="CY" DateFrom="2010-08-13" DateTo="2020-08-13"/>
<PlayerRegistration PersonFIFAId="105C3Z1" Status="active" OrganisationFIFAId="105C40I " RegistrationValidFrom="2003-04-11" RegistrationValidTo="2009-06-15" Discipline="Football" Level="Amateur"/>
<PlayerRegistration PersonFIFAId="105C3Z1" Status="active" OrganisationFIFAId="105C40I " RegistrationValidFrom="2009-06-16" Discipline="Football" Level="Pro"/>
<TeamOfficialRegistration PersonFIFAId="105C3Z1" Status="active" OrganisationFIFAId="105C40I" RegistrationValidFrom="2012-08-13" RegistrationValidTo="2014-08-13" Discipline="Futsal" TeamOfficialRole="Coach"/>
</PersonLocal>
Additionally an instance of the BackgroundListener
class exposes the following events:
PersonDetailsRequestReceived
PersonDetailsReceived
GenericMessageReceived
ServiceBusExceptionEvent
These events are automatically raised by the listener. You can use them to register your own event handlers and provide additional logic for handling received messages.
listener.PersonDetailsReceived += details =>
{
// do something with those details
};
listener.GenericMessageReceived += message =>
{
var bytes = message.Content;
var actionName = message.Action;
};
If a message received from Connect Service Bus is processed properly by all registered handlers (no exceptions are thrown), then the message is marked as processed and deleted from the Connect Service Bus queue. In case any handler throws an exception, a message will not be deleted from the Connect Service Bus but will be scheduled for later processing. BackgroundListener
will try to process this message, but after a series of unsuccessful handles, a message will be moved to a dead messages queue, which will be monitored by FIFA Connect ID Helpdesk.
First create a person you want to register:
var organisationId = "id";
// setup player name(s)
var personNames = new List<PersonName>
{
new PersonName("John", "Doe")
};
// setup birthdate
var dateOfBirth = new DateTime(1990, 10, 12);
var person = new PersonType
{
DateOfBirth = dateOfBirth
};
// setup registrations
var registration = new PlayerRegistrationType
{
OrganisationFIFAId = organisationId,
Status = "active",
Level = "Pro",
Discipline = "Football"
};
person.PlayerRegistrations = new List<PlayerRegistrationType>
{
registration
};
// finally create PersonData
var personData = new PersonData(personNames, person);
Then try to register a person using Registration Facade. The code snippet below shows an example handling (writing to console) of both scenarios, i.e. successful registration and potential duplicates found.
var result = await facade.RegisterPersonAndWaitForDetailsInCaseOfDuplicates(
personData.Person.ToString(), TimeSpan.FromSeconds(10)).ConfigureAwait(false);
if (result.IsSuccessful)
{
Console.WriteLine($"Person successfully registered with unique FIFA ID: {result.UniqueFifaId}.");
}
else {
Console.WriteLine("Duplicates found.");
foreach (var duplicateWithDetails in result.PersonDuplicateWithDetails)
{
var idOfDuplicatedPerson = duplicateWithDetails.Duplicate.PersonFifaId;
var proximityScore = duplicateWithDetails.Duplicate.ProximityScore;
var dataReceived = duplicateWithDetails.PersonDetails == null
? "<detailed person data not received from other MA - timeout>"
: duplicateWithDetails.PersonDetails.XmlData;
Console.WriteLine($"FIFA ID: {idOfDuplicatedPerson}, score: {proximityScore}, FIFA Data XML: {dataReceived}");
}
}
SDK provides support for registering a person with multiple names. Two scenarios will usually require such a feature:
Support for such a scenario depends on the way person registration is used.
If you use RegisterPersonAsync
which takes XML in FIFA Data Standard as a parameter, make sure that the following attributes of PersonLocal
(PersonLocal schema) are filled:
LocalFirstName
LocalLastName
LocalBirthName
InternationalFirstName
InternationalLastName
You don't need to do anything else, as SDK will take care of parsing XML and sending data to the server.
Fifa.ConnectId.Sdk.Core.XmlParser.Models.PersonData
In this case, before registering a person, you need to create a list of pairs of names (List<PersonName>
) . The following example shows the most sophisticated scenario when a single person has both: local name, international name and maiden name provided. Although two pairs of names will be used in minority of cases and three pairs hardly ever, the example is instructive.
var internationalFirstName = "Olga";
var internationalLastName = " Terekhova";
var localFirstName = "Ольга";
var localLastName = "Терехова";
var localMaidenName = "Бессолова";
var personInternationalName = new PersonName(internationalFirstName, internationalLastName);
var personLocalName = new PersonName(localFirstName, localLastName);
var personMaidenName = new PersonName(localFirstName, localMaidenName);
// setup player name(s)
var personNames = new List<PersonName>();
personNames.Add(personInternationalName);
personNames.Add(personLocalName);
personNames.Add(personMaidenName);
First create two persons and register them:
// setup player name(s)
var person1Names = new List<PersonName>
{
new PersonName("John", "Doe")
};
var person2Names = new List<PersonName>
{
new PersonName("John", "Kowalsky")
};
// setup birthdate
var dateOfBirth = new DateTime(1990, 10, 12);
var person = new PersonType
{
DateOfBirth = dateOfBirth
};
// setup registrations
var registration = new PlayerRegistrationType
{
OrganisationFIFAId = organisationId,
Status = "active",
Level = "Pro",
Discipline = "Football"
};
person.PlayerRegistrations = new List<PlayerRegistrationType>
{
registration
};
// finally create PersonData
var person1Data = new PersonData(person1Names, person);
var person2Data = new PersonData(person2Names, person);
//register two different players
facade.ForceRegisterPerson(person1Data);
facade.ForceRegisterPerson(person2Data);
Then try to update second person using Registration Facade with names of first person. The code snippet below shows an example handling (writing to console) of both scenarios, i.e. successful update and potential duplicates found.
var result = await facade.UpdatePersonAndWaitForDetailsInCaseOfDuplicates(personId, TimeSpan.FromSeconds(10), names, dateOfBirth).ConfigureAwait(false);
if (result.IsSuccessful)
{
Console.WriteLine($"Person updated successfully.");
}
else
{
Console.WriteLine("Duplicates found.");
foreach (var duplicateWithDetails in result.PersonDuplicateWithDetails)
{
var idOfDuplicatedPerson = duplicateWithDetails.Duplicate.PersonFifaId;
var proximityScore = duplicateWithDetails.Duplicate.ProximityScore;
var dataReceived = duplicateWithDetails.PersonDetails == null
? "<detailed person data not received from other MA - timeout>"
: duplicateWithDetails.PersonDetails.XmlData;
Console.WriteLine($"FIFA ID: {idOfDuplicatedPerson}, score: {proximityScore}, FIFA Data XML: {dataReceived}");
}
}
If you need to get list of duplicates for a person, method GetDuplicatesAndWaitForDetailsInCaseOfDuplicates
can be used. This methods looks for duplicates in Connect ID service. If any duplicate is found requests for person details are sent to relevant MAs.
var foundDuplicates = await facade.GetDuplicatesAndWaitForDetailsInCaseOfDuplicates(personData, TimeSpan.FromSeconds(10)).ConfigureAwait(false);
if (foundDuplicates.Count > 0)
{
Console.WriteLine("Duplicates found.");
foreach (var duplicateWithDetails in foundDuplicates)
{
var idOfDuplicatedPerson = duplicateWithDetails.Duplicate.PersonFifaId;
var proximityScore = duplicateWithDetails.Duplicate.ProximityScore;
var dataReceived = duplicateWithDetails.PersonDetails == null
? "<detailed person data not received from other MA - timeout>"
: duplicateWithDetails.PersonDetails.XmlData;
Console.WriteLine($"FIFA ID: {idOfDuplicatedPerson}, score: {proximityScore}, FIFA Data XML: {dataReceived}");
}
}
If your infrastructure for the application using SDK consists of multiple servers, then additional configuration is required. In such setup RegistrationFacade
needs a kind of storage where it can store state of communication with Connect Service Bus. In order to achieve SDK has interface PersonDetailsCache
which must be implemented by the client of SDK and passed into RegistrationFacadeSettings
.
Examples of implementation of PersonDetailsCache
are:
Code snippet below presents how to register YourSharedStorage
in RegistrationFacade
:
var settings = new RegistrationFacadeSettings
{
PersonDetailsCache = new YourSharedStorage()
};
var facade = new RegistrationFacade(environment, clientCredentials, settings);
In the above example YourSharedStorage
implements mentioned PersonDetailsCache
interface by providing three methods:
void Put(PersonDetails personDetails)
- inserts records in shared storagePersonDetails GetByCorrelationId(String correlationId)
- gets record from shared storage by idvoid DeleteOlderThan(Duration duration)
- for cleanup purposes it deletes old recordspublic interface IPersonDetailsCache
{
/// <summary>
/// Puts person details into storage mechanism.
/// </summary>
void Put(PersonDetails personDetails);
/// <summary>
/// Get person details with given correlation id from storage mechanism.
/// </summary>
PersonDetails GetByCorrelationId(string correlationId);
/// <summary>
/// Deletes the entries from storage mechanism that are older than given date.
/// </summary>
void DeleteOlderThan(TimeSpan duration);
}
Registration Facade covers scenario of person registration/update/search, but for other functionalities FIFA ID Client described in the next chapter must be used.
In particular FIFA Connect ID Client must be used for:
Currently there is no request throttling in API, but it's recommended not to exceed 10 concurrent connections. Too many requests to API may result in requests time outs. In case you plan to do a batch import of person records, please contact support team so that the infrastructure can be scaled up accordingly.
This chapter discusses all operations on a Person entity, e.g. Registration, Update, Merge, etc. It is different from chapter 3.1 Using Registration Facade in that operations described here do not involve a duplicate check. A developer who wants to perform a duplicate check via Service Bus should either refer to chapter 3.1 or implement communication via Service Bus by themselves.
The entry point of the SDK is FifaConnectIdClient
. With a single instance of this class all the requests can be made. In order to authenticate to the service you have to provide a set of client credentials.
var environment = ConnectIdEnvironment.Beta;
var credentials = new ClientCredentials("clientId", "secretKey");
var client = new FifaConnectIdClient(environment, credentials);
where environment is an instance of type ConnectIdEnvironment
. It provides information about the service to make request to.
By default, the above constructor uses a NullLogger
, which does nothing. However, to use logging, provide your own implementation of ILogger
.
ILogger logger = new YourOwnLogger();
var client = new FifaConnectIdClient(environment, clientCredentials, logger);
In addition you can provide information about the current user interacting with the Registration System. This can be accomplished by providing implementation of IActorResolver
interface. Such actor resolver could be much more advanced than SimpleActorResolver
provided as a default implementation. In case of web application, actor could be fetched from current web request context.
IActorResolver actorResolver = new SimpleActorResolver("John Doe");
var client = new FifaConnectIdClient(environment, clientCredentials, logger, actorResolver);
In order to register a person in FIFA Connect ID service, provide a properly formatted xml string. The root of the xml should be PersonLocal
, not PersonData
. It is required to define a local name in the document by giving LocalFirstName
and LocalLastName
attributes. In addition to that, LocalBirthName
can by used - in that case the pair of names will be created together with LocalFirstName
. International version (optional) of the name can by specified with attributes InternationalFirstName
and InternationalLastName
. See details:
And an example:
try
{
var uniqueFifaId = await client.RegisterPersonAsync(xml);
}
catch (XmlException ex)
{
// the delivered XML is malformed
}
catch(AuthenticationException ex)
{
// invalid client credentials
}
catch(UnauthorizedException ex)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaDuplicatedEntityFoundException ex)
{
// possible duplicates were found
var duplicates = ex.GetDuplicatesResponseType.Duplicates;
}
catch (FifaConnectIdException ex)
{
// some other error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
Instead of using XML files, you can also populate fields of the PersonData
object yourself. For your convenience all the methods accepting XML as an input also accept PersonData
directly. Here is an example, analogical to 3.2.2:
var names = new[]
{
new PersonName("ΑΓΓΕΛΗΣ", "ΧΑΡΑΛΑΜΠΟΥΣ"), // local name
new PersonName("ANGELIS", "CHARALAMBOUS") // international name
};
var person = new PersonType
{
DateOfBirth = new DateTime(1980, 10, 10, 0, 0, 0, DateTimeKind.Utc),
// fill up registrations
};
var personData = new PersonData(names, person);
try
{
var uniqueFifaId = await client.RegisterPersonAsync(personData);
}
catch(AuthenticationException ex)
{
// invalid client credentials
}
catch(UnauthorizedException ex)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaDuplicatedEntityFoundException ex)
{
// possible duplicates were found
var duplicates = ex.GetDuplicatesResponseType.Duplicates;
}
catch (FifaConnectIdException ex)
{
// some other error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
In order to register persons in parallel you can use Task Parallel Library. Please note that in order to optimize costs of test environment we keep it small-scale. Let us know upfront if you plan to test bulk registration, so we can scale up the environment. Additionally we recommend not exceeding 20 concurrent registrations to avoid performance degradation of the service. Take a look at the following example:
var database = new LocalDatabase();
var players = database.Players.Where(x => x.FifaId == null);
players
.AsParallel()
.WithDegreeOfParallelism(10)
.ForAll(player =>
{
PersonData personData = CreatePerson(player);
string fifaId = client.RegisterPersonAsync(personData).Result;
database.UpdateFifaId(player.Id, fifaId);
});
To force the registration process (proceed even if potential duplicates are found):
try
{
var uniqueFifaId = await client.ForceRegisterPersonAsync(xml);
}
catch (XmlException ex)
{
// the delivered XML is malformed
}
catch(AuthenticationException ex)
{
// invalid client credentials
}
catch(UnauthorizedException ex)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaConnectIdException ex)
{
// some other error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
This method will throw FifaPersonMergedException
when you try to get data for a person that has been previously merged (refer to section 4.5 Merging persons). The exception will contain data about requested person together with primary person id. To get the information associated with the specified FIFA ID such as a date of birth or list of person's registrations:
try
{
var uniqueFifaId = "BVGE8T6";
var person = await client.GetPersonAsync(uniqueFifaId);
}
catch(AuthenticationException ex)
{
// invalid client credentials
}
catch(UnauthorizedException ex)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find the person
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaPersonMergedException ex)
{
// requested person has been merged
var person = ex.RequestedEntity;
var primaryPersonId = ex.PrimaryEntityId;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
To merge two persons into a single one use MergePersonsAsync
method available on FifaConnectIdClient
. This affects getting secondary person data in the future. Please refer to section 3.2.4 Getting person data. Here is an example how to merge persons:
try
{
var person = await client.MergePersonsAsync(primaryPersonId, secondaryPersonId).ConfigureAwait(false);
}
catch (AuthenticationException ex)
{
// invalid client credentials
var details = ex.HttpOperationResponse;
}
catch (UnauthorizedException ex)
{
// unauthorized
var details = ex.HttpOperationResponse;
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find one of specified persons
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
In order to revert merge operation call UnmergePersonsAsync
method with the same arguments.
To get a list of people a person may be duplicated with:
try
{
var potentialDuplicates = await client.GetDuplicatesAsync(xml);
}
catch (XmlException ex)
{
// the delivered XML is malformed
}
catch(AuthenticationException ex)
{
// invalid client credentials
}
catch(UnauthorizedException ex)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
This method is expected to be used rarely, e.g. in cases when Registration System chooses to do a duplicate check without the registration.
XML is the same as described in 3.2.2.
It is possible to update an existing person record (provided that we know the person's FIFA ID) by adding, editing or removing its registrations. In order to do that, use the class AddRegistrationsRequestType
, UpdateRegistrationsRequestType
or RemoveRegistrationsRequestType
(depending on the operation) and fill information about the registrations. Note, that each person always contains four collections of registrations:
In the examples below, only player registrations are used - the other 3 collections remain empty (they are not set).
Add a single player registration to an existing person with a given ID. Note that in the example below a registration is added in a National Association and not in a Club. This is not a coincidence - FIFA Connect ID Service, although allowed to store Clubs in general, is not allowed to store persons' assignments to Clubs. Server will return an error should the Client try to register a person within a Club.
const string personId = "105C408";
const string organisationId = "105KYBB";
var exampleRegistration = new PlayerRegistrationType();
exampleRegistration.Level = "Pro";
exampleRegistration.Discipline = "Football";
exampleRegistration.OrganisationFIFAId = organisationId;
exampleRegistration.Status = "Active";
var personRegistrations = new PersonRegistrationsType();
personRegistrations.PlayerRegistrations = new List<PlayerRegistrationType>();
personRegistrations.PlayerRegistrations.Add(exampleRegistration);
var request = new AddRegistrationsRequestType(personId, personRegistrations);
try
{
var personType = await client.AddRegistrations(request, false).ConfigureAwait(false);
}
catch(AuthenticationException ex)
{
// invalid client credentials
}
catch(UnauthorizedException ex)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find the person
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
Update single player registration. In order to execute a request we need to know the registrations we need to update and their new values. Note that the order of registrations is important. Operation will try to change the first item in "old" list with the first item in the "new" list, etc.
const string personId = "105C408";
const string organisationId = "105KYBB";
var person = await client.GetPersonAsync(personId).ConfigureAwait(false);
var oldPersonRegistrations = new PersonRegistrationsType();
oldPersonRegistrations.PlayerRegistrations = person.PlayerRegistrations;
var newPlayerRegistration = new PlayerRegistrationType();
newPlayerRegistration.Level = "Pro";
newPlayerRegistration.Discipline = "Football";
newPlayerRegistration.Status = "Active";
newPlayerRegistration.OrganisationFIFAId = organisationId;
var newPersonRegistrations = new PersonRegistrationsType();
newPersonRegistrations.PlayerRegistrations.Add(newPlayerRegistration);
var request = new UpdateRegistrationsRequestType(personId,
oldPersonRegistrations,
newPersonRegistrations
);
try
{
var personType = await client.UpdateRegistrations(request, false).ConfigureAwait(false);
}
catch(AuthenticationException ex)
{
// invalid client credentials
}
catch(UnauthorizedException ex)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find the person
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
Remove player registrations from an existing person with a given ID
const string personId = "105C408";
var person = await client.GetPersonAsync(personId).ConfigureAwait(false);
var registrationsToRemove = new PersonRegistrationsType();
registrationsToRemove.PlayerRegistrations = person.PlayerRegistrations;
var request = new RemoveRegistrationsRequestType(personId, registrationsToRemove);
try
{
var personType = await client.RemoveRegistrations(request, false).ConfigureAwait(false);
}
catch(AuthenticationException ex)
{
// invalid client credentials
}
catch(UnauthorizedException ex)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find the person
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
Please note that each time an operation succeed, you will receive an object of class PersonType
containing the current status of a person with all their registrations. This feature may be used for troubleshooting but also to synchronize the local data with a central DB (ID Directory).
Also note that errors are not thrown if you perform an operation which would result in the object not changing its state. For example, if you want to add a registration for a Football Player, Amateur in France, and such a registration already exists, error will not be thrown and the operation will succeed.
To update a person associated with the specified FIFA ID:
try
{
var names = new List<PersonName>();
names.Add(new PersonName("first name", "last name"));
var updatedPerson = await client.UpdatePersonAsync("105C40T", names, new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc)).ConfigureAwait(false);
}
catch (AuthenticationException ex)
{
// invalid client credentials
var details = ex.HttpOperationResponse;
}
catch (UnauthorizedException ex)
{
// unauthorized
var details = ex.HttpOperationResponse;
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find the person
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
To register a new organisation:
var organisation = new OrganisationType
{
Status = "active",
OrganisationNature = "WorldFederation",
// fill up all required data according to FIFA Data Standard
};
try
{
var uniqueFifaId = await client.RegisterOrganisationAsync(organisation).ConfigureAwait(false);
}
catch (AuthenticationException)
{
// invalid client credentials
}
catch (UnauthorizedException)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaConnectIdException ex)
{
// some other error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
To get the organisation data associated with the specified FIFA ID use GetOrganisationAsync
method. This method will throw FifaOrganisationMergedException
when you try to get data for an organisation that has been previously merged and deactivated (refer to section 4.10 Merging organisations). The exception will contain data about requested organisation together with primary organisation id.
try
{
var uniqueFifaId = "BVGE8TG";
var organisation = await client.GetOrganisationAsync(uniqueFifaId).ConfigureAwait(false);
}
catch (AuthenticationException ex)
{
// invalid client credentials
var response = ex.HttpOperationResponse;
}
catch (UnauthorizedException ex)
{
// unauthorized
var response = ex.HttpOperationResponse;
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find the organisation
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaOrganisationMergedException ex)
{
// requested organisation has been merged and is inactive
var organisation = ex.RequestedEntity;
var primaryOrganisationId = ex.PrimaryEntityId;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
To merge two organisations into a single one use MergeOrganisationsAsync
method available on FifaConnectIdClient
. This operation will only work for clubs. In addition you can only merge those that belong to the same member association that you are a member of. As a result of this operation, secondary organisation status will be set to inactive
. This affects getting secondary organisation data in the future. Please refer to section 4.2 Getting organisation data. Here is an example how to merge organisations:
try
{
var organisation = await client.MergeOrganisationsAsync(primaryOrganisationId, secondaryOrganisationId).ConfigureAwait(false);
}
catch (AuthenticationException ex)
{
// invalid client credentials
var details = ex.HttpOperationResponse;
}
catch (UnauthorizedException ex)
{
// unauthorized
var details = ex.HttpOperationResponse;
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find one of specified organisations
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
To update the organisation data use UpdateOrganisationAsync
method.
try
{
var organisationId = "BVGE8TG";
var organisation = await client.GetOrganisationAsync(organisationId).ConfigureAwait(false);
// modify data
organisation.Status = "inactive";
organisation.Email = "some@other.email";
var updatedOrganisation = await client.UpdateOrganisationAsync(organisation).ConfigureAwait(false);
}
catch (AuthenticationException ex)
{
// invalid client credentials
var details = ex.HttpOperationResponse;
}
catch (UnauthorizedException ex)
{
// unauthorized
var details = ex.HttpOperationResponse;
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find the organisation
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
To search for an organisation use SearchOrganisation
method. It takes SearchOrganisationRequestType
as a parameter that aggregates search criteria. It's possible to search by international and local names, parent organisation, organisation nature, and address.
try
{
var request = new SearchOrganisationRequestType
{
InternationalName = "Barcelona",
OfficialAddress = new SearchAddressType
{
Country = "ES",
Town = "Barcelona"
},
NumberOfResults = 5
};
var response = await client.SearchOrganisation(request).ConfigureAwait(false);
var foundOrganisations = response.Organisations;
}
catch (AuthenticationException ex)
{
// invalid client credentials
var details = ex.HttpOperationResponse;
}
catch (UnauthorizedException ex)
{
// unauthorized
var details = ex.HttpOperationResponse;
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
To register a new facility:
var facility = new FacilityType()
{
Status = "active",
InternationalName = "Wembley Stadium",
OrganisationFIFAId = "BVGE8TG"
// fill up all required data according to FIFA Data Standard
};
try
{
var uniqueFifaId = await client.RegisterFacilityAsync(facility).ConfigureAwait(false);
}
catch(AuthenticationException ex)
{
// invalid client credentials
}
catch(UnauthorizedException ex)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaConnectIdException ex)
{
// some other error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
To get the facility data associated with the specified FIFA ID:
try
{
var uniqueFifaId = "105C40T";
var facility = await client.GetFacilityAsync(uniqueFifaId).ConfigureAwait(false);
}
catch(AuthenticationException ex)
{
// invalid client credentials
}
catch(UnauthorizedException ex)
{
// unauthorized
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find the facility
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
To update the facility data use UpdateFacilityAsync
method.
try
{
var facilityId = "105C40T";
var facility = await client.GetFacilityAsync(facilityId).ConfigureAwait(false);
// set the data to update
facility.Email = "some@other.email";
facility.Status = "inactive";
var updatedFacility = await client.UpdateFacilityAsync(facility).ConfigureAwait(false);
}
catch (AuthenticationException ex)
{
// invalid client credentials
var details = ex.HttpOperationResponse;
}
catch (UnauthorizedException ex)
{
// unauthorized
var details = ex.HttpOperationResponse;
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
catch (FifaEntityNotFoundException ex)
{
// could not find the facility
var operationResponse = ex.HttpOperationResponse;
}
catch (FifaConnectIdException ex)
{
// some error occurred, see the details
var operationResponse = ex.HttpOperationResponse;
}
To search for a facility use SearchFacility
method. It takes SearchFacilityRequestType
as a parameter that aggregates search criteria. It's possible to search by international and local names, parent facility, organisation, and address.
try
{
var request = new SearchFacilityRequestType
{
InternationalName = "Camp Nou",
OfficialAddress = new SearchAddressType
{
Country = "ES",
Town = "Barcelona"
},
NumberOfResults = 5
};
var response = await client.SearchFacility(request).ConfigureAwait(false);
var foundFacilities = response.Facilities;
}
catch (AuthenticationException ex)
{
// invalid client credentials
var details = ex.HttpOperationResponse;
}
catch (UnauthorizedException ex)
{
// unauthorized
var details = ex.HttpOperationResponse;
}
catch (InvalidClientDataException ex)
{
// data sent to the service was invalid
var details = ex.BadRequestResponse;
}
The following changes were introduced in version 4.1 of the SDK when comparing to version 3.1:
PictureType
contains all required information from FIFA data standardUpdatePersonAndWaitForDetailsInCaseOfDuplicates
into RegistrationFacade
SearchOrganisation
into FifaConnectIdClient
SearchFacility
into FifaConnectIdClient
UnmergePersonsAsync
in FifaConnectIdClient
.IActorResolver
.