Home > database >  How can I express this nested loop in LINQ?
How can I express this nested loop in LINQ?

Time:10-25

Background:

  • I have ASP.NET Core app. I'm trying to write server-side validation errors to the log.
  • If ASP.NET Core model validation detects any error in any field in the webform, then ModelState.IsValid is false.
  • Every field in the webform is listed in ModelState.Values
  • If a "Value" has one or more errors, then Value.Errors.Count > 0
  • I want to log a) the webform field name (the Value's "key") and b) each error message for that field.
  • I'd like to include all this information in a single line (i.e. a single C# "string").

Current code:

// LOG:
//   2022-10-24 09:37:29.0909|Error|ServiceMenu.Q255: The value '' is invalid. 
//   2022-10-24 09:37:35.4096|Error|ServiceMenu.Q265: The value '' is invalid. 
if (!ModelState.IsValid)
{
    foreach (var k in ModelState.Keys)
    {
        var v = ModelState[k];
        if (v.Errors.Count > 0)
        {
            string s = k   ": ";
            for (int i=0; i < v.Errors.Count - 1; i  )
                s  = v.Errors[i].ErrorMessage   ", ";
            s  = v.Errors[v.Errors.Count - 1].ErrorMessage;
            _logger.LogError(s);
        }
    }
    return Page();
}

Sample output (two required fields, Q255 and 265, were blank):

2022-10-24 09:37:29.0909|Error|ServiceMenu.Q255: The value '' is invalid. 
2022-10-24 09:37:35.4096|Error|ServiceMenu.Q265: The value '' is invalid. 

Q: Can I simplify this nested loop with LINQ?


Update:

  • Thank you, everybody.

  • Evk and T.S. are both absolutely correct: "Don't think that using LINQ is always good." I don't - and their point is very well taken :)

  • Oliver Weichhold gave me the syntax I was looking for :)

  • Here's the code I finally wound up with:

    // EXAMPLE LOG:
    //   2022-10-24 13:24:10.5242|Error|ServiceMenu.Q255: The value '' is invalid. 
    //   2022-10-24 13:24:24.9692|Error|ServiceMenu.Q265: The value '' is invalid. 
    if (!ModelState.IsValid)
    {
        foreach (var k in ModelState.Keys)
        {
            var v = ModelState[k];
            if (v.Errors.Count > 0)
            {
                string s = string.Join(", ", ModelState[k].Errors
                    .Select(x => x.ErrorMessage));
                _logger.LogError(k   ": "   s);
            }
        }
        ...
    

CodePudding user response:

if (!ModelState.IsValid)
{
    var logMessage = string.Join("\n", ModelState.Keys
        .Where(x => ModelState[x].Errors?.Count > 0)
        .Select(x => $"{x}: "   string.Join(", ", ModelState[x].Errors.Select(y => y.ErrorMessage))));
        
    _logger.LogError(logMessage);
}
  • Related