Предупреждения модели в ASP.NET MVC - PullRequest
6 голосов
/ 15 декабря 2008

В настоящее время я использую ModelStateDictionary в asp.net mvc для хранения ошибок проверки и передачи обратно пользователю. Возможность проверить, является ли вся модель действительной с ModelState.IsValid особенно. Однако текущее приложение, над которым я работаю, должно иметь возможность сообщать о предупреждениях. Они не так критичны, поэтому содержимое формы можно сохранить, но их следует показать пользователю, чтобы при желании можно было выполнить какое-либо действие.

Я просматривал фреймворк, чтобы увидеть, есть ли какое-нибудь очевидное место для его расширения, чтобы я мог это сделать. Я думаю, что другой словарь с предупреждениями и подклассом ошибки модели называется предупреждением модели. Я не уверен, как заставить фреймворк использовать мои новые классы контейнеров в представлении и т. Д., Хотя я все еще хочу, чтобы все существующие ошибки работали.

Если кто-то пробовал что-то подобное или у меня есть какие-либо мысли, я был бы признателен за их вклад.

Обновление:

Я дошел до расширения ViewDataDictionary для добавления некоторых предупреждений

public class AetherViewDataDictionary : ViewDataDictionary
{
    public AetherViewDataDictionary()
    {
        ModelStateWarning = new ModelStateDictionary();
    }

    public AetherViewDataDictionary(object model) : base(model)
    {
        ModelStateWarning = new ModelStateDictionary();
    }

    public AetherViewDataDictionary(ViewDataDictionary viewDataDictionary) : base(viewDataDictionary) 
    {
        ModelStateWarning = new ModelStateDictionary();
    }

    public ModelStateDictionary ModelStateWarning { get; private set; }
}

Проблема, с которой я столкнулся сейчас, заключается в том, что когда я получаю код моего вида, это просто для отладки, я теряю тот факт, что это мой новый тип, поэтому, когда я пытаюсь привести его обратно и получить доступ мой новый словарь у меня нет радости.

public partial class Index : ViewPage<PageViewData>
{
    protected override void SetViewData(ViewDataDictionary viewData)
    {
        base.SetViewData(viewData);
    }
}

Здесь он установлен правильно, но когда я проверяю тип, он исчез.

Edit: Это оказался глупый способ делать что-то, см. Ответ ниже.

Ответы [ 3 ]

6 голосов
/ 16 декабря 2008

Так что маршрут, который я направлял вниз, оказался плохой идеей, в фреймворке просто недостаточно доступа, чтобы добраться до нужных вам битов. По крайней мере, не изобретая колесо несколько раз.

Я решил пойти по пути расширения класса ModelState, чтобы добавить в него коллекцию предупреждений:

public class AetherModelState : ModelState
{
    public AetherModelState() { }

    public AetherModelState(ModelState state)
    {
        this.AttemptedValue = state.AttemptedValue;

        foreach (var error in state.Errors)
            this.Errors.Add(error);
    }

    private ModelErrorCollection _warnings = new ModelErrorCollection();

    public ModelErrorCollection Warnings { get { return this._warnings; } }
}

Чтобы можно было легко добавлять предупреждения так же, как и в случае ошибок, я создал несколько методов расширения для ModelStateDictionary:

public static class ModelStateDictionaryExtensions
{
    public static void AddModelWarning(this ModelStateDictionary msd, string key, Exception exception)
    {
        GetModelStateForKey(key, msd).Warnings.Add(exception);
    }

    public static void AddModelWarning(this ModelStateDictionary msd, string key, string errorMessage)
    {
        GetModelStateForKey(key, msd).Warnings.Add(errorMessage);
    }

    private static AetherModelState GetModelStateForKey(string key, ModelStateDictionary msd)
    {
        ModelState state;
        if (string.IsNullOrEmpty(key))
            throw new ArgumentException("key");

        if (!msd.TryGetValue(key, out state))
        {
            msd[key] = state = new AetherModelState();
        }

        if (!(state is AetherModelState))
        {
            msd.Remove(key);
            msd[key] = state = new AetherModelState(state);
        }

        return state as AetherModelState;
    }

    public static bool HasWarnings(this ModelStateDictionary msd)
    {
        return msd.Values.Any<ModelState>(delegate(ModelState modelState)
        {
            var aState = modelState as AetherModelState;
            if (aState == null) return true;
            return (aState.Warnings.Count == 0);
        });
    }
}

Код GetModelStateForKey не совсем понятен, но вы должны увидеть, к чему я клоню. Следующее, что нужно сделать, - это написать несколько методов расширения, которые позволяют отображать предупреждения вместе с ошибками

4 голосов
/ 15 декабря 2008

Почему бы просто не добавить список предупреждений или словарь в ViewData и затем отобразить их в своем представлении?

, например

ViewData[ "warnings" ] = new[] { "You need to snarfle your aardvark" } ;
0 голосов
/ 17 октября 2018

Я использовал решение от Саймона Фэрроу в качестве отправной точки, чтобы заставить предупреждения работать с источником данных Кендо. По умолчанию вы можете вернуться и показать Data ИЛИ Errors, но я хотел вернуться и показать Data И Warnings. Поэтому я обернул DataSourceResult Кендо и добавил еще один метод расширения, который возвращает собранные предупреждения.

// The wrapper
public class DataSourceResultWithWarnings: DataSourceResult
{
    public object Warnings { get; }

    public DataSourceResultWithWarnings(DataSourceResult dataSourceResult, IDictionary<string, IDictionary<string, IList<string>>> warnings)
    {
        this.AggregateResults = dataSourceResult.AggregateResults;
        this.Data = dataSourceResult.Data;
        this.Errors = dataSourceResult.Errors;
        this.Total = dataSourceResult.Total;
        Warnings = warnings;
    }
}

// The extension method
public static IDictionary<string, IDictionary<string, IList<string>>> GetWarnings(this ModelStateDictionary msd)
{
    var result = new Dictionary<string, IDictionary<string, IList<string>>>();

    for (var i = 0; i < msd.Values.Count; i++)
    {
        var wms = msd.Values.ElementAt(i) as WarningModelState;
        if (wms != null)
        {
            if (!result.ContainsKey(msd.Keys.ElementAt(i)))
            {
                result.Add(msd.Keys.ElementAt(i), new Dictionary<string, IList<string>>() { { "warnings", new List<string>() } });
            }
            result[msd.Keys.ElementAt(i)]["warnings"].AddRange((from rec in wms.Warnings select rec.ErrorMessage));
        }
    }

    return result;
}

// How to use it in the controller action
var result = new DataSourceResultWithWarnings(files.Values.ToDataSourceResult(request, ModelState), ModelState.GetWarnings());
return Json(result, JsonRequestBehavior.AllowGet);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...