Green Grasso Holm
Green Grasso Holm

Reputation: 704

Bind an array of .NET Core configuration sections to a class or List<class>

I thought it would be useful to define the data for error reporting in a configuration file, say, errordefinitions.json:

{
  "errorDefinitions": {
    "unsupportedExtension": {
      "errorLevel": 2,
      "doLog": true,
      "logMessage": "The file {0} doesn't have a valid extension for this operation.",
      "doEmail": false,
      "emailSubject": "",
      "emailBody": ""
    },
    "fileOpenFailed": {
      "errorLevel": 3,
      ...
    }
  }
}

or

[
  {
    "name":"unsupportedExtension",
    "errorLevel": 2,
    "doLog": true,
    "logMessage": "The file {0} doesn't have a valid extension for this operation.",
    "doEmail": false,
    "emailSubject": "",
    "emailBody": ""
  },
  {
    "name": "fileOpenFailed",
    "errorLevel": 3,
    ...
  }
]

Either way, my expectation was that I'd be able to use Microsoft's built-in configuration management classes to define a class and then fairly straightforwardly bind a class, or a list of items in a class, to these so that I could reference them thus:

(UPDATE I've expanded my example below since I first posted to show more clearly what I have in mind. I want to be able to look up and use an error definition based on its name, without having to wrap each definition in a separate class. A dictionary, essentially, without the application being semantically aware of the meaning of each entry.

When I add a new feature to the application, I want to be able to add the data for any new errors that the new feature may encounter to the configuration file and address those by name as well, without having to add new classes to the error handling infrastructure.

Also, for what it's worth, this is for server-side use--this isn't a result I'm returning to a client.)

{
  ...
  try
  {
    openFile(file);
    ...
  }
  catch (Exception e)
  {
    handleError("fileOpenFailed", file.name);
    ...
  }
  ...
}

public void handleError(string errorName, params object[] values)
{
  ErrorDefinition errorDef = ErrorDefinitions[errorName];
  if (errorDev.doLog)
  {
    writeToLog(
      errorDef.errorLevel,
      String.Format(errorDef.logMessage, values)
    );
  }
  if (errorDef.doEmail)
  {
    sendNotificationToEmailList(
      errorDef.emailSsubject,
      errorDef.emailBody
    );
  }
  ...
}

But I've gotten lost in the API. SectionGroups, SectionCollections, SectionGroupCollections; some of them enumerable, some not. Any tips?

Upvotes: 0

Views: 1070

Answers (1)

Rena
Rena

Reputation: 36715

It seems that you want map the json file data to the model.

Here is a working demo:

Model:

public class ErrorDefinition
{
    public Dictionary<string, Dictionary<string,string>> errorDefinitions
    {
        get;
        set;
    }
}

Controller:

public ActionResult Index()
{
    var configuration = new ConfigurationBuilder()
                        .SetBasePath(Directory.GetCurrentDirectory())
                        .AddJsonFile("errordefinitions.json", false)
                        .Build();

    var config = configuration.Get<ErrorDefinition>();
    var data = config.errorDefinitions["fileOpenFailed"]
                        .FirstOrDefault(x=>x.Key== "logMessage").Value;
    return View();
}

errordefinitions.json in root project:

{
  "errorDefinitions": {
    "unsupportedExtension": {
      "errorLevel": 2,
      "doLog": true,
      "logMessage": "The file {0} doesn't have a valid extension for this operation.",
      "doEmail": false,
      "emailSubject": "",
      "emailBody": ""
    },
    "fileOpenFailed": {
      "errorLevel": 3,
      "doLog": true,
      "logMessage": "The file {0} cannot be opened.",
      "doEmail": false,
      "emailSubject": "",
      "emailBody": ""
    }
  }
}

Result:

enter image description here

Upvotes: 2

Related Questions