title: Post Knockout.js viewmodel to ASP.NET MVC Controller action using ajax results in null-values
body: <p>I'm building a simple CMS for a website. The site is built with asp.net mvc and I'm using knockout.js for two-way binding. I can send my values from DB to my view and change the model values. My problem comes when I try to save the modified viewmodel.
  I'm saving the data in DB using the following class:</p>
  
  <pre><code>public class Content
  {
      public int ContentId { get; set; }
      public string Name { get; set; }
      public string Value { get; set; }
  }
  </code></pre>
  
  <p>My full viewmodel:</p>
  
  <pre><code>public class CmsStartPageViewModel
  {
      public string SectionOneTitle {get; set;}
      public string SectionOneText {get; set;}
      public string SectionTwoTitle {get; set;}
      public string SectionTwoText {get; set;}
      public string SectionThreeTitle {get; set;}
      public string SectionFourTitle {get; set;}
      public string BannerOneTitle {get; set;}
      public string BannerOneSubTitle {get; set;}
      public string BannerOneIcon {get; set;}
      public string SectionFiveTitle {get; set;}
      public string SectionFiveSubTitle {get; set;}
      public string ContactTitle {get; set;}
      public string ContactSubTitleOne {get; set;}
      public string ContactText {get; set;}
      public string ContactSubTitleDetails {get; set;}
      public string ContactSubTitleSocial {get; set;}
  
      public List&lt;SupportingCompany&gt; SupportingCompanies { get; set; }
      public List&lt;ReasonTemplate&gt; ReasonTemplates { get; set; }
      public List&lt;ProductInfoTemplate&gt; ProductInfoTemplates { get; set; }
  
      //Kontaktformulär Validering
  
      public string FormFullName { get; set; }
      public string FormEmail { get; set; }
      public string FormSubject { get; set; }
      public string FormMessage { get; set; }
  
  
      public void PopulateViewModel(ICollection&lt;StartContent&gt; data)
      {
          var self = this;
  
          var properties = typeof(CmsStartPageViewModel).GetProperties();
  
          foreach (PropertyInfo property in properties)
          {
              var type = property.PropertyType;
              if (type == typeof(String) &amp;! property.Name.StartsWith("Form"))
              {
                  var value = data.Single(d =&gt; d.Name == property.Name);
                  property.SetValue(self, value.Value);
              }
          }
      }
  }
  </code></pre>
  
  <p>My save-function (knockout.js viewmodel):</p>
  
  <pre><code>ViewModel = function(data) {
      var self = this;
      ko.mapping.fromJS(data, {}, self);
  
      self.save = function () {
          var model = ko.mapping.toJSON(self);
          $.ajax({
              url: "/Cms/SaveViewModel",
              type: "POST",
              data: model,
              dataType: "json",
              contentType: "json",
              success: function(message) {
                  ko.mapping.fromJS(data.viewModel, {}, self);
                  if (message.Status === "success") {
                      toastr.success(message.Content);
                  } else if (message.Status === "error") {
                      toastr.error(message.Content);
                  }
              }
          });
      }
  }
  </code></pre>
  
  <p>And finally, my Save action method:</p>
  
  <pre><code>    [HttpPost]
      public ActionResult SaveViewModel(CmsPageViewModel model)
      {
          var content = _contentRepo.GetStartContent();
  
          foreach (var item in content)
          {
              var property = model.GetType().GetProperty(item.Name);
              property.SetValue(model, item.Value);
          }
  
          _contentRepo.UpdateStartContent(content);
  
          var message = new StatusMessageCms
          {
              Content = "Your changes has now been saved!",
              Status = "success"
          };
  
          return Json(message);
      }
  </code></pre>
  
  <h2>Update:</h2>
  
  <p>The JSON-model that's getting sent to server. I can't find any mismatches with my C# Viewmodel</p>
  
  <pre><code>    {
      "SectionOneTitle": "Aja-Baja.se avskräcker stöld och bedrägerier",
      "SectionOneText": "När vi blir tillräckligt många, kan vi stöldförsäkra till ett subventionerat pris.&lt;br /&gt;\nIntresse från flera försäkringsbolag finns",
      "SectionTwoTitle": "Om Aja-Baja.se",
      "SectionTwoText": "Vi är två crossmotionärer som ser ett växande problem med stölder av motorcrosscyklar. För att förhindra detta så startar vi ett register där alla kan registrera sina crossar. &lt;br /&gt;&lt;br /&gt;\n\nDU vill inte köpa en stulen cross och inte heller bli bestulen på dem. Om alla som har en cross eller tänker köpa en, använder registret och sökfunktionen så hjälps vi åt att hålla koll så att det inte blir så intressant att stjäla dem.",
      "SectionThreeTitle": "Varför ska du registrera dig?",
      "SectionFourTitle": "Priser &amp; Specifikationer",
      "BannerOneTitle": "Samarbeta mot inbrottstjuvarna",
      "BannerOneSubTitle": "REGISTRERA DIG HOS AJA-BAJA OCH HÅLL KOLL DU MED!",
      "BannerOneIcon": "fa-users",
      "SectionFiveTitle": "Vi är inte de enda som är entusiastiska inför Aja-Baja.se...",
      "SectionFiveSubTitle": "Flera samarbetspartners tror på vår idé",
      "ContactTitle": "Kontakta Oss",
      "ContactSubTitleOne": "Gör oss &lt;strong&gt;Bättre&lt;/strong&gt;",
      "ContactText": "Det är viktigt för oss och veta vad ni som besökare tycker om vår Mobilapp och Webbapplikation. Har ni ett förslag på vad som skulle kunna göras bättre? Eller är det något som ni saknar? Fyll isåfall i formuläret och skicka det till oss. Tillsammans är vi starka!",
      "ContactSubTitleDetails": "Aja-Bajas &lt;strong&gt;Kontaktuppgifter&lt;/strong&gt;",
      "ContactSubTitleSocial": "Sociala &lt;strong&gt;Medier&lt;/strong&gt;",
      "SupportingCompanies": [{
          "SupportingCompanyId": 1,
          "ImageUrl": "/Content/img/sponsor/alternativ_mc_sponsor.png",
          "LinkUrl": "http://www.alternativ1mc.se/"
      }, {
          "SupportingCompanyId": 2,
          "ImageUrl": "/Content/img/sponsor/eliasson_racing.png",
          "LinkUrl": "http://www.eliassonracing.se/"
      }, {
          "SupportingCompanyId": 3,
          "ImageUrl": "/Content/img/sponsor/KonicaMinolta_Logo.png",
          "LinkUrl": "http://www.konicaminolta.se/sv/home.html"
      }, {
          "SupportingCompanyId": 4,
          "ImageUrl": "/Content/img/sponsor/frisk_sponsor.png",
          "LinkUrl": null
      }],
      "ReasonTemplates": [{
          "ReasonTemplateId": 1,
          "ReasonTitle": "Sökbarhet",
          "ReasonText": "Möjlighet att via ramnummer se om crossen är stulen.",
          "ReasonIcon": "fa-search"
      }, {
          "ReasonTemplateId": 2,
          "ReasonTitle": "Stöldanmälning",
          "ReasonText": "Anmäl snabbt din cross stulen via app eller hemsida.",
          "ReasonIcon": "fa-bullhorn"
      }, {
          "ReasonTemplateId": 3,
          "ReasonTitle": "Samarbetspartners",
          "ReasonText": "Verkstäder och återförsäljare kan kontrollera om crossen är stulen.",
          "ReasonIcon": "fa-users"
      }, {
          "ReasonTemplateId": 4,
          "ReasonTitle": "Ägarbyten",
          "ReasonText": "Ett smidigt och säkert sätt att registrera ett ägarbyte.",
          "ReasonIcon": "fa-refresh"
      }, {
          "ReasonTemplateId": 6,
          "ReasonTitle": "Motverka stölder",
          "ReasonText": "Stöldanmälda registrerade crossar blir svårare att sälja vidare.",
          "ReasonIcon": "fa-lock"
      }, {
          "ReasonTemplateId": 8,
          "ReasonTitle": "Förmåner som kund",
          "ReasonText": "Rabatter hos utvalda verkstäder och butiker.",
          "ReasonIcon": "fa-user"
      }],
      "ProductInfoTemplates": [],
      "FormFullName": null,
      "FormEmail": null,
      "FormSubject": null,
      "FormMessage": null
  }
  </code></pre>
  
  <p><strong>Edited question</strong></p>
  
  <p>The issue I encounter is that when I try to post to the controller all values are null. The ajax hits the correct Action and I can't find any differences between my posted JSON-model and my C# viewmodel.</p>
  
  <p>Any help is appreciated!</p>
  
  <p>Martin Johansson</p>