2014-10-22 15 views
8

Mam formularz, który jest generowany przez jQuery:Jquery Post ASP.NET API kontrolera

$.get("/api/get/getListItems", function (data) { 
       var table = ""; 
       table += "<table>"; 
       $.each(data, function (y, z) { 
        console.log(z); 
        table += '<tr>'; 
        $.each(this, function (k, v) { 
         table += '<td><input type="text" name="' + k + '" id="' + k + '" value="' + v + '" /></td>'; 
        }); 
        table += '<td><input type="checkbox" name="selected" id="selected" /></td>'; 

        table += '</tr>'; 
       }); 
       table += '<tr><td><input type="submit" id="submit" name="submit" value="Save To Database" /></td></tr>'; 
       table += '</table>'; 
       $('#form').html(table); 
      }); 

i generuje ten kod HTML (10 wierszy pól wejściowych, 7 kolumn i 1 pole wyboru): http://jsfiddle.net/8zpr2fkL/1/

a ja wysłaniu formularza, gdy przycisk submit kliknięciu:

$("#form").submit(function (event) { 
     $.post("/api/update/", $("#form").serialize(), alert('success')); 
    }); 

teraz jestem przekazując dane do mojego ASP.NET API kontroler:

[HttpPost] 
     public dynamic Post([FromBody]CellModel cells) 
     { 
       UpdateClass jobs = new UpdateClass(); 
       return jobs; 
     } 

i tu jest moja klasa CellModel:

public class CellModel 
    { 
     public uint scheduleTaskID { get; set; } 
     public string task { get; set; } 
     public string baselineDate { get; set; } 
     public string scheduledDate { get; set; } 
     public string actualDate { get; set; } 
     public string finishedDate { get; set; } 
     public bool selected { get; set; } 

     public override string ToString() 
     { 
      return scheduleTaskID.ToString(); 
     } 
    } 

mój problem jest, gdy uderzę złożyć do przekazywania danych i umieścić punkt przerwania na metodzie kontrolera komórki liczyć wynosi 0, jest tam coś jestem tu brakuje? Próbuję przekazać wszystkie dane w tekście wejściowym do kontrolera. Nic nie dostaje się do mojego kontrolera. Co ja robię źle?

to dane im stara się przekazać poprzez jquery $ ('forma #') serializacji().

scheduleTaskID=194&task=Permit&baselineDate=6%2F23%2F2005+8%3A00%3A00+AM&scheduledDate=6%2F23%2F2005+8%3A00%3A00+AM&actualDate=6%2F23%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=195&task=Office+Files&baselineDate=7%2F13%2F2005+8%3A00%3A00+AM&scheduledDate=7%2F13%2F2005+8%3A00%3A00+AM&actualDate=7%2F13%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=196&task=Foundation&baselineDate=7%2F27%2F2005+8%3A00%3A00+AM&scheduledDate=7%2F27%2F2005+8%3A00%3A00+AM&actualDate=8%2F13%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=197&task=Framing&baselineDate=8%2F5%2F2005+8%3A00%3A00+AM&scheduledDate=8%2F5%2F2005+8%3A00%3A00+AM&actualDate=8%2F23%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=198&task=Finishes+Exterior&baselineDate=8%2F26%2F2005+8%3A00%3A00+AM&scheduledDate=8%2F26%2F2005+8%3A00%3A00+AM&actualDate=9%2F14%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=199&task=Drywall&baselineDate=9%2F2%2F2005+8%3A00%3A00+AM&scheduledDate=9%2F2%2F2005+8%3A00%3A00+AM&actualDate=9%2F16%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=200&task=Flooring&baselineDate=9%2F1%2F2005+8%3A00%3A00+AM&scheduledDate=9%2F1%2F2005+8%3A00%3A00+AM&actualDate=9%2F20%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=201&task=General+Finish&baselineDate=9%2F12%2F2005+8%3A00%3A00+AM&scheduledDate=9%2F12%2F2005+8%3A00%3A00+AM&actualDate=&finishedDate=&scheduleTaskID=202&task=Final+PDI&baselineDate=10%2F11%2F2005+8%3A00%3A00+AM&scheduledDate=10%2F11%2F2005+8%3A00%3A00+AM&actualDate=&finishedDate=&scheduleTaskID=203&task=Permit&baselineDate=4%2F6%2F2005+8%3A00%3A00+AM&scheduledDate=4%2F6%2F2005+8%3A00%3A00+AM&actualDate=4%2F6%2F2005+8%3A00%3A00+AM&finishedDate= 

UPDATE

zmieniłem:

$("#form").submit(function (event) { 
      $.post("/api/update/", $("#form").serialize(), alert('success')); 
     }); 

to

$("#form").submit(function (event) { 
     var array = []; 
     $('#form > table > tbody > tr').each(function (elem) { 
      var item = {}; 
      item.scheduleTaskID = $(this).find("td > #scheduleTaskID").val(); 
      item.task = $(this).find("td > #task").val(); 
      item.baselineDate = $(this).find("td > #baselineDate").val(); 
      item.scheduledDate = $(this).find("td > #scheduledDate").val(); 
      item.actualDate = $(this).find("td > #actualDate").val(); 
      item.finishedDate = $(this).find("td > #finishedDate").val(); 
      item.selected = $(this).find("td > #selected").val(); 
      array.push(item); 
     }); 
     console.log(JSON.stringify(array)); 
     $.post("/api/update/", JSON.stringify(array), alert('success'), 'json'); 
    }); 

w moim konsoli zalogować moich danych wygląda następująco:

[{"scheduleTaskID":"203","task":"Permit","baselineDate":"4/6/2005 8:00:00 AM","scheduledDate":"4/6/2005 8:00:00 AM","actualDate":"4/6/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"195","task":"Office Files","baselineDate":"7/13/2005 8:00:00 AM","scheduledDate":"7/13/2005 8:00:00 AM","actualDate":"7/13/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"196","task":"Foundation","baselineDate":"7/27/2005 8:00:00 AM","scheduledDate":"7/27/2005 8:00:00 AM","actualDate":"8/13/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"197","task":"Framing","baselineDate":"8/5/2005 8:00:00 AM","scheduledDate":"8/5/2005 8:00:00 AM","actualDate":"8/23/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"198","task":"Finishes Exterior","baselineDate":"8/26/2005 8:00:00 AM","scheduledDate":"8/26/2005 8:00:00 AM","actualDate":"9/14/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"199","task":"Drywall","baselineDate":"9/2/2005 8:00:00 AM","scheduledDate":"9/2/2005 8:00:00 AM","actualDate":"9/16/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"200","task":"Flooring","baselineDate":"9/1/2005 8:00:00 AM","scheduledDate":"9/1/2005 8:00:00 AM","actualDate":"9/20/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"201","task":"General Finish","baselineDate":"9/12/2005 8:00:00 AM","scheduledDate":"9/12/2005 8:00:00 AM","actualDate":"","finishedDate":"","selected":"on"},{"scheduleTaskID":"202","task":"Final PDI","baselineDate":"10/11/2005 8:00:00 AM","scheduledDate":"10/11/2005 8:00:00 AM","actualDate":"","finishedDate":"","selected":"on"},{"scheduleTaskID":"203","task":"Permit","baselineDate":"4/6/2005 8:00:00 AM","scheduledDate":"4/6/2005 8:00:00 AM","actualDate":"4/6/2005 8:00:00 AM","finishedDate":"","selected":"on"},{}] 

iw moim ASP.NET API kontrolera, zmieniłem metodę do tego:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net; 
using System.Net.Http; 
using System.Web.Http; 
using MvcApplication1.Models; 

namespace MvcApplication1.Controllers 
{ 
    public class UpdateController : ApiController 
    { 
     [HttpPost] 
     public dynamic Post(List<CellModel> cells) 
     { 
       UpdateClass jobs = new UpdateClass(); 
       //jobs.PostScheduledTasks(cells); 
       return cells; 
     } 

    } 
} 

I umieścić punkt przerwania na początku metoda Post i kiedy trafia w punkt przerwania, mówi komórka Count = 0.. Widzę połączenie sieciowe, tylko jeśli po fakcie i po wysłaniu zwracam wartość false, a odpowiedź jest pusta [] Dlaczego dane nie przekazują do kontrolera, czy to dlatego, że formularz jest generowany przez jquery?

UPDATE

Nadal nie rozwiązanie, spojrzałem na moje wezwanie sieci to AM i kod stanu jest 301:

enter image description here

+1

Nie powinna to być lista CellModels? Wygląda na to, że odsyłasz więcej niż 1 ... To może nie rozwiązać problemu, ale jest czymś, na co trzeba patrzeć ... –

+0

Tak, wysyłam więcej niż jedną ... – user979331

+0

Jeszcze jedna rzecz do wypróbowania. Czy usunąłeś [FromBody] ze swojego postu? Czy są to dane generowane z czegoś podobnego do Fiddlr? Czy to właśnie przechodzi przez sieć? –

Odpowiedz

19

Nie używaj $ .post użytkowania ajax posta i ustaw typ zawartości na "application/json; charset = utf-8"

var data = JSON.stringify(array); 
$.ajax({ 
    url:"/api/update/", 
    type:"POST", 
    data:data, 
    contentType:"application/json; charset=utf-8", 
    dataType:"json", 
    success: function(data){ 
    console.log(data); 
    } 
}); 

Problem polega na tym, że musisz powiedzieć serwerowi internetowemu, że wysyłasz json i nie jest to możliwe z $.zakładać

To jest naprawdę normalny, a ja zmaga się z tym zbyt (a czasami jeszcze zapomnieć), tutaj można zobaczyć, że trzeba użyć $ .ajax

Jquery - How to make $.post() use contentType=application/json?

+0

Tak, !!!! to zadziałało :) Bardzo dziękuję – user979331

+2

@ user979331 Działa, ale ma gorszą wydajność czasoprzestrzeni niż rozwiązanie wykorzystujące $ .post (sprawdź moją odpowiedź). Konwertujesz elementy formularza do JSON w pętli foreach i wykonujesz powtarzające się wyszukiwanie DOM przy użyciu jQuery, które jest całkowicie niepotrzebne. Łatwiej jest po prostu serializować formularz i publikować, jeśli postępujesz zgodnie z zasadami opisanymi poniżej. –

+0

@TheZenCoder, nie znałem twojego podejścia, jest dobre, ale po przeczytaniu wszystkich linków, które znalazłem, utrata wydajności po stronie klienta jest nikczemna. (szczerze mówiąc) Nie mogłem pracować z ogromnymi formularzami, nie znam innych, ale średnia forma, którą możesz stworzyć, nie ma strat. W każdym razie głosowałem za twoim podejściem jako pozytywnym. Miłego weekendu: D – dariogriffo

0

wiem, to jest już rozwiązane przy użyciu .ajax zamiast .post. Pomyślałem o udostępnieniu tego, ponieważ rozwiązałem to przy użyciu .post. Jak wspomniano powyżej, ponieważ publikuje treść o typie Content-Type:application/x-www-form-urlencoded; charset=UTF-8, parametr cells w metodzie post będzie zawierał count = 0.

Aby rozwiązać ten problem, należy ręcznie przechwycić obiekt żądania i pobrać dane pocztowe, a następnie dokonać deserializacji i uzyskać obiekt jako List<CellModel>. Użyłem całego opublikowanego kodu przez OP, i właśnie zmodyfikowałem metodę post, jak pokazano poniżej, i zadziałało.

[HttpPost] 
public dynamic Post(List<CellModel> cells) 
{ 
    string content = string.Empty; 
    if (HttpContext.Current.Request.InputStream.CanSeek) 
    { 
     HttpContext.Current.Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin); 
    } 
    using (System.IO.StreamReader reader = new System.IO.StreamReader(HttpContext.Current.Request.InputStream)) 
    { 
     content = reader.ReadToEnd(); 
    } 
    if (!string.IsNullOrEmpty(content)) 
    { 
     // Deserialize and operate over cells. 
     try 
     { 
      var obj = Newtonsoft.Json.JsonConvert.DeserializeObject(content, typeof(List<CellModel>)); 
     } 
     catch (Exception ex) 
     { 
      return ex; 
     } 

    } 
    return cells; 
} 

Oto, co otrzymam podczas debugowania.

enter image description here

enter image description here

+0

Załóżmy, że masz 120 punktów końcowych POST w swoim interfejsie API, to jest całkowicie nie do zapamiętania. – dariogriffo

+0

Nie wiem, jaki będzie na to OP, jeśli jesteś tego świadomy, daj mi znać, właśnie próbowałem rozwiązać z .post', i to jest wykonalne. Ale tak, '.ajax' jest najlepszym sposobem na obsługę' HTTPPost' używanego w webapi. –

4

ile masz alternatywnego podejścia @dariogriffo, chcę dać Ci pełne rozwiązanie z użyciem początkowego podejścia z $ .post.

Początkowe podejście z formy serializacji było prawidłowe, więc następujący kod jest poprawny:

$("#form").submit(function (event) { 
    $.post("/api/update/", $("#form").serialize(), alert('success')); 
}); 

Jednak to nie działa, ponieważ Twój dynamiczna forma nie przestrzega konwencji nazewnictwa dla pól wejściowych oczekiwanych przez domyślny spinacz modelu ASP.NET MVC, w wyniku czego Twoja serializowana postać nie była czymś, co domyślny segregator modelu mógł powiązać z modelem cells. Właśnie dlatego nie otrzymujesz żadnych komórek w kontrolerze podczas wykonywania testu POST.

Aby wyjaśnić, co to znaczy, ASP.NET oczekuje każde pole wejściowe odpowiada właściwości modelu, aby mieć następujący format nazwy jeśli Piszesz do regularnego MVC 5 Kontroler:

actionattributename[index].propertyname 

Jeżeli jesteś wpis do Web API 2 kontrolera powinno być:

[index].propertyname 

Ponieważ atrybut akcja nosi nazwę cells i ma właściwości scheduledTaskID i Piszesz do kontrolera WebAPI jeden ze swoich wejść wyglądałby następująco:

<input type="text" name="[0].scheduleTaskID" id="scheduleTaskID" value="194"> 

Istnieje kilka dodatkowych reguł związanych z budową formularza, aby uczynić go wiążącym. Można znaleźć ładne blogu o tym tutaj:

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

Jeśli po tej konwencji formularz będzie można zamieścić swoje zserializowaną formularza do kontrolera spodziewa się List<CellModel> cellsbez konieczności korzystania z podejścia JSON, który jest o wiele droższy od, co sugerują inne odpowiedzi.

Poniżej znajduje się skrzypce z przykładowy formularz prawidłowo zorganizowanego przez 2 domyślnych reguł wiążących Web API:

http://jsfiddle.net/8zpr2fkL/12/

można spróbować $ .post tej formie przy użyciu $ .post do kontrolera Web API i powinien działać jak urok!

+0

Podoba mi się również to rozwiązanie – dariogriffo

Powiązane problemy