Search code examples
wcfasp.net-mvc-3validationwcf-client

How to display validation exceptions received from WCF service in MVC3 app


I have a MVC3 app that uses WCF services for data access. WCF services uses EF4.1 for data access.

I want minimum dependencies between MVC3 app and WCF services, so they don't share any libraries. The only dependency in MVC3 app is the service reference.

To validate entities on save, I defined the operation contracts on WCF services to generate FaultContract defined as below:

[OperationContract]
[FaultContract(typeof(EntityFault))]
void AddAddressEntity(Address entity); 

EntityFault is defined as below:

[DataContract(IsReference=true)]
public class EntityFault
{
    [DataMember]
    public string ErrorMessage { get; set; }
    [DataMember]
    public virtual ICollection<ValidationErrorMessage> ValidationErrorMessages 
        { get; set; }
}

and ValidationErrorMessage is a simple class with two properties, PropertyName and ValidationMessage

I trap DbEntityValidationException as below:

try
{  //....    
    db.SaveChanges();
}
catch (DbEntityValidationException ex)
{
    EntityFault ef = EntityFaultHelper.CreateValidationFault(ex, entity);
    throw new FaultException<EntityFault>(ef, ef.ErrorMessage);
}

In my MCV3 app I intercept the fault exception. But how can I display the error messages either in

@Html.ValidationMessageFor(<my specific field>)

or in

@Html.ValidationSummary(...) 

section?

If the model fields were annotated, or if the client entity implements IValidatableObject, error msgs are displayed in specified areas.

One idea is to use ViewBag, and define display placeholders for error msgs received from WCF's FaultContract, and set the corresponding ViewPag dinamic properties for received error msgs.

But I'm wondering if there's a better approach.

Thanks


Solution

  • So far I found the following solution

    I added for each field in the view a placeholder to display error message as below:

        <div class="editor-label">
            @Html.LabelFor(model => model.State)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.State)            
            @ViewBag.StateError                
        </div>
    

    Then in the controller I have this code

    using (var addressClient = new AddressServiceClient(_configName))
    {
        try
        {
            addressClient.AddAddressEntity(address);
            return RedirectToAction("Index");
        }
        catch (FaultException<EntityFault> ex)
        {
            foreach (var err in ex.Detail.ValidationErrorMessages)
            {
                ViewData.Add(
                    string.Format("{0}Error", err.PropertyName),
                    err.ErrorMessage);
            }
        }
    }
    

    And it display the errors right next to fields.

    But I'm still wondering if there's a way to use the placeholders

    @Html.ValidationMessageFor(model => model.Address1)  
    

    or

    @Html.ValidationSummary(true)
    

    The reason is, I don't want to have to manually change all the Create / Edit views generated by MVC3 VS helper, I prefer to find a way to reuse those placeholders.

    Edit

    I found a better solution. It works directly with the view generated by MVC out of the box.
    The key code is to set the error messages in ModelState as below

    try
    {
        addressClient.AddAddressEntity(address);
        return RedirectToAction("Index");
    }
    catch (FaultException<EntityFault> ex)
    {
        foreach (var err in ex.Detail.ValidationErrorMessages)
            this.ModelState.AddModelError(err.PropertyName, err.ErrorMessage);
    }
    

    The point is in ModelState there is a key for each model field (property), with property name as key. So by adding model error for that property, the error message is displayed in the corresponding place for validation error