Предупреждения модели в ASP.NET MVC

В настоящее время я использую 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);
    }
}

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

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

15.12.2008 09:23:33
3 ОТВЕТА

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

например

ViewData[ "warnings" ] = new[] { "You need to snarfle your aardvark" } ;
4
15.12.2008 12:00:39
Потому что ViewDataне являются частью ответа при выполнении запроса AJAX. Что, скорее всего, имеет место здесь. Вы можете использовать, ViewDataесли вы загрузите новую страницу.
Carsten Franke 17.10.2018 08:05:44
РЕШЕНИЕ

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

Я решил пойти по пути расширения класса 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 не совсем понятен, но вы должны увидеть, к чему я клоню. Следующее, что нужно сделать, это написать несколько методов расширения, которые позволяют мне отображать предупреждения вместе с ошибками

6
16.12.2008 09:14:42
Что такое AttemptedValue?
Mahmoud Moravej 14.01.2015 10:49:49
Также "if (aState == null) вернет true;" линия неверна. Мы должны вернуть true, если и только если в связанной коллекции есть хотя бы один элемент. Поэтому вы должны удалить эту строку и изменить следующую строку на «return (aState! = Null && aState.Warnings.Count> 0);»
Mahmoud Moravej 14.01.2015 11:46:31

Я использовал решение от Саймона Фэрроу в качестве отправной точки, чтобы заставить предупреждения работать с источником данных Кендо. По умолчанию вы можете вернуться и показать DataOR , Errorsно я хотел бы вернуться и показать Dataи Warnings. Поэтому я обернул Kendo 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);
0
17.10.2018 08:00:29