Контроллер ASP.NET Web API не может обрабатывать динамические объекты? - PullRequest
3 голосов
/ 24 февраля 2012

В моем коде у меня есть базовый класс Foo, и все мои объекты наследуются от объекта Foo.Допустим, у меня есть такой класс

public class Bar : Foo {
    public string Heading { get;set; }
}

Я пытался использовать метод ApiControllers put с динамическим, но я получаю эту ошибку http://paste2.org/p/1914054

Это код, который яиспользование в ApiController

public void Put(string id, dynamic model) {
    //do stuff
}

Если я использую обычный контроллер, я могу использовать динамический для публикации данных.Можно ли добавить, чтобы контроллер API работал с динамическим, или мне нужно создать свою собственную модель связующего?

Похоже, что некоторые думают, что даже в MVC 3 входные параметры не могут быть динамическими, но этоэто не правда, и поэтому я задаю этот вопрос. Этот контроллер в MVC 3 прекрасно работает с динамическим входным параметром.

Ответы [ 3 ]

3 голосов
/ 20 апреля 2012

Хм, я смог сделать это с помощью метода ASP.NET Web API:

    public string Post(dynamic value)
    {
        string s = "";
        foreach (dynamic item in value)
        {
            s = s + item.content + " ";
        }
        return s;
    }

с использованием массива JSON:

POST http://localhost:6946/api/values HTTP/1.1
User-Agent: Fiddler
Host: localhost:6946
Content-Length: 327
Content-Type: application/json
[{"content":"Hello","editing":false},{"content":"sfsdf","editing":false},{"content":"sadsdfdsf","editing":false},{"content":"dfsdf","editing":false},{"content":"dsfsd","editing":false},{"content":"sdfsdf","editing":false},{"content":"dsf","editing":false},{"content":"dfg","editing":false},{"content":"fsdfsd","editing":false}]

И это сработало ....

1 голос
/ 25 февраля 2012

Видно, что некоторые думают, что даже в MVC 3 входные параметры не могут будь динамичным

Я так думаю. Давайте посмотрим на приведенный пример:

[HttpPost]
[ValidateInput(false)]
public virtual ActionResult Update(dynamic editorModel) {

    if (!TryUpdateModel(_model, "CurrentModel")) {
        var parentId = _model.Parent != null ? (string)_model.Parent.Id : null;
        var viewModel = new EditViewModel
        {
            RootModel = _session.Query<IPageModel>()
                .Where(model => model.Parent == null)
                .SingleOrDefault(),
            CurrentModel = _model,
            ParentModel = parentId != null ? _session.Load<IPageModel>(parentId) : null,
        };
        return View("edit", viewModel);
    }

    UpdateModel(_model);

    _model.Metadata.Changed = DateTime.Now;
    _model.Metadata.Published = _model.Metadata.IsPublished ? DateTime.Now : default(DateTime?);
    _model.Metadata.ChangedBy = HttpContext.User.Identity.Name;

    _repository.SaveChanges();
    _repository.Refresh(_model);

    var page = _model as IPageModel;

    if (page.Parent != null) {
        _model = _repository.SingleOrDefault<IPageModel>(m => m.Id == page.Parent.Id);
    }

    return RedirectToAction("index", new { model = _model });
}

Можете ли вы указать мне, как / где именно эта editorModel динамическая переменная используется внутри этого действия контроллера?

И чтобы еще больше упростить это действие контроллера, оно работает, потому что оно никогда не использует динамическую переменную, переданную в качестве аргумента. Я упростил его, чтобы лучше проиллюстрировать, что это действие примерно выполняет в отношении привязки модели (конечно, отбрасывая весь шум инфраструктуры, который нам здесь не интересен, чтобы проиллюстрировать проблему):

[HttpPost]
public ActionResult Update(dynamic blablabla)
{
    dynamic model = new MyViewModel();
    UpdateModel(model);
    // at this stage the model will be correctly bound

    return View(model);
}

Внутри этого действия методы TryUpdateModel и UpdateModel вызываются для переменной экземпляра _model, которая передается в конструкторе и имеет тип IPageModel. ASP.NET MVC не может знать (конечно, без привязки к пользовательской модели) тип аргумента динамического действия. Просто запустите этот код, поместите точку останова в действие Update и наблюдайте тип переменной editorModel. Это будет просто System.Object. Чудес не бывает.

Так что для меня совершенно нормально, что это работает так же в ASP.NET Web API.

0 голосов
/ 04 декабря 2015

http://www.binaryintellect.net/articles/589f6915-f4c0-4bf9-9f94-4d00bd445c16.aspx

Это решение отлично работает.

У меня была HTML-форма, где все элементы управления вводом были динамическими. Трудно было перенести данные формы на контроллер MVC, а затем снова на контроллер Web Api 2.

Ваш метод веб-API на стороне сервера должен быть похож на

public string Post(FormDataCollection form){
... }

FormDataCollection находится в пространстве имен System.Net.Http.Formatting.

Если вы представляете данные непосредственно с веб-страницы (jquery), то вышеуказанное решение для ссылок работает нормально.

Если вы публикуете веб-страницу данных на странице MVC (код C #), которая затем дополнительно публикуется в методе веб-API, код выглядит следующим образом:

[HttpPost]
    public async Task<string> MasterDraw(FormCollection body)
    {
        HttpClient client = new HttpClient();
        KeyValuePair<string, string>[] list = null;
        string url = ConfigurationManager.AppSettings["BaseServiceUrl"] + "/api/MasterOperation/addrecord";

        if (body != null && body.HasKeys())
        {
            list = new KeyValuePair<string, string>[body.AllKeys.Count()];
            for (int ctr = 0; ctr < body.Keys.Count; ctr++ )
            {
                list[ctr] = new KeyValuePair<string, string>(body.Keys[ctr], body.GetValue(body.Keys[ctr]).AttemptedValue);
            }
        }

        var content = new FormUrlEncodedContent(list);

        HttpResponseMessage response = await client.PostAsync(url, content);

        // Check that response was successful or throw exception
        response.EnsureSuccessStatusCode();

        // Read response asynchronously as JToken and write out top facts for each country
        string contentRes = response.Content.ReadAsStringAsync().Result;

        return contentRes;
    }

Код браузера:

$('#btn-save').on('click', function (event) {
            var postUrl = "@Url.Action("masterdraw","masterrender")";

            var result = $.ajax({
                type: "POST",
                data: $('#form').serialize(),
                url: postUrl                    
            });

            // insert your jquery .done and .error methods

        });
...