text:
layout: post
title: Post a collection of ViewModel's to a MVC Action with jQuery
category: jQuery
---

Maybe I searched for the wrong thing, but I couldn't find what I was looking for :( My Bing and Google fu failed me.

Basically I wanted to post a collection of ViewModels to an MCV action. Turns out it's rather simple.

Lets say I have a bunch of Products, and Products are managed in a WarehouseLocation. A product doesn't have a warehouse location, since it could exist in multiple locations.

If I'm currently working in Location A, I want to post a collection of Products to an action, as well as the WarehouseLocationId.

So given a simple ViewModel, and an Action:

    public class ProductViewModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }

and

<!--excerpt-->

    public JsonResult Update(int warehouseLocationId, IEnumerable<ProductViewModel> products)
    {
        //Do something with the products...
        return Json(new {Staus = "success"});
    }

I think usually when someone sends data from jQuery it's usually a single parameter,so the JSON would look something like:

    var data = { id: 1,name: 'test name', price: 15.95 };

This would populate an action that looked like:

    public JsonResult Update(ProductViewModel product)

But what I was faced with was passing in two parameters, one of which is a collection...

MVC seems to pair up the posted result with the parameter name, in the same way they it does for Route parameters. So to the JSON needs to look like:

    var data = {
        warehouseLocationId: 12,
        products: [{
            Id: 1,
            Name: "Product 1",
            Price: 15.95
        }, {
            Id: 3,
            Name: "Product 2",
            Price: 12.50
        }]
    };

As you can see the key's on the first level match the parameter names, while the array on products, match the ViewModel.

Taking this exact data and posting it to the action:

    $.ajax({
        type: 'POST',
        url: '@Url.Action("Update", "Home")',
        data: JSON.stringify(data),
        contentType: 'application/json',
        success: function(result) {
            //Do something with result...
        },
        dataType: 'json'
    });

I submit that, and with a breakpoint on my action I see:

![](/images/jquery-mvc-1.png)

^ The warehouseLocationId...

![](/images/jquery-mvc-2.png)

^ 2 products with the values:

![](/images/jquery-mvc-3.png)

And:

![](/images/jquery-mvc-4.png)

The exact same data we defined in our JavaScript.

The really cool thing about this, is you can have nested collections also. Using the same scenario, but extending Product to have a collection of Categories like so:

    public class ProductViewModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public IEnumerable<Category> Categories { get; set; }
    }

    public class Category
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

I can update the JSON object to include Category information on 1 of the two products:

    var data = {
        warehouseLocationId: 12,
        products: [{
            Id: 1,
            Name: "Product 1",
            Price: 15.95
        }, {
            Id: 3,
            Name: "Product 2",
            Price: 12.50,
            Categories: [{
                Id: 1,
                Name: "Category 1"
            }, {
                Id: 1,
                Name: "Category 2"
            }]
        }]
    };

And submit that in the same way as before, capturing the results in the Action we get the first product with null for the categories, since we didn't define it as an empty array:

![](/images/jquery-mvc-5.png)

While the second Product has 2 items, the first item is Category 1, and the second item is Category 2.

![](/images/jquery-mvc-6.png)

![](/images/jquery-mvc-7.png)

And that's it, easy peasy, sending a collection of ViewModels from jQuery to an MVC Action.

I <3 MVC :)


text:
class Member < ActiveRecord::Base
  attr_accessible :email, :first, :last, :nickname
  include MailManager::ContactableRegistry::Contactable
end
MailManager::ContactableRegistry.register_contactable("Member",
{
    :first_name => :first,
      :last_name=> :last,
        :email_address=> :email
})

redpajama_set_name: RedPajamaGithub


text:
layout: post
microblog: true
date: 2013-10-15 23:25 +0300
guid: http://desparoz.micro.blog/2013/10/15/t390211760512172033.html
---
Judging by all the people looking for new hosting after GoDaddy bought Media Temple, I suspect that GoDaddy hasn't bought a customer base


text:
def sanitize_databases(databases)
  sanitized_dbs = databases.to_a # avoid node objects are read only warnings

  sanitized_dbs.delete('netgroup') if platform?('debian') && node['platform_version'].to_i < 8

  if platform_family?('rhel') && node['platform_version'].to_i < 6
    sanitized_dbs.delete('netgroup')
    sanitized_dbs.delete('services')
  end

  sanitized_dbs
end

def nscd_user
  # if the user set the value use that
  return node['nscd']['server_user'] if node['nscd']['server_user']

  Etc.getpwnam('nscd')
  'nscd'
rescue ArgumentError
  'nobody'
end


text:
/*
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
/*
 * This code was generated by https://github.com/googleapis/google-api-java-client-services/
 * Modify at your own risk.
 */

package com.google.api.services.artifactregistry.v1.model;

/**
 * The response of the completed artifact upload operation. This response is contained in the
 * Operation and available to users.
 *
 *
 This is the Java data model class that specifies how to parse/serialize into the JSON that is
 * transmitted over HTTP when working with the Artifact Registry API. For a detailed explanation
 * see:
 * https://developers.google.com/api-client-library/java/google-http-java-client/json
 *

 *
 * @author Google, Inc.
 */
@SuppressWarnings("javadoc")
public final class UploadAptArtifactResponse extends com.google.api.client.json.GenericJson {

  /**
   * The Apt artifacts updated.
   * The value may be {@code null}.
   */
  @com.google.api.client.util.Key
  private java.util.List<AptArtifact> aptArtifacts;

  static {
    // hack to force ProGuard to consider AptArtifact used, since otherwise it would be stripped out
    // see https://github.com/google/google-api-java-client/issues/543
    com.google.api.client.util.Data.nullOf(AptArtifact.class);
  }

  /**
   * The Apt artifacts updated.
   * @return value or {@code null} for none
   */
  public java.util.List<AptArtifact> getAptArtifacts() {
    return aptArtifacts;
  }

  /**
   * The Apt artifacts updated.
   * @param aptArtifacts aptArtifacts or {@code null} for none
   */
  public UploadAptArtifactResponse setAptArtifacts(java.util.List<AptArtifact> aptArtifacts) {
    this.aptArtifacts = aptArtifacts;
    return this;
  }

  @Override
  public UploadAptArtifactResponse set(String fieldName, Object value) {
    return (UploadAptArtifactResponse) super.set(fieldName, value);
  }

  @Override
  public UploadAptArtifactResponse clone() {
    return (UploadAptArtifactResponse) super.clone();
  }

}


text:
require 'sequel' # http://sequel.jeremyevans.net/rdoc/files/doc/cheat_sheet_rdoc.html
require 'sequel_secure_password'

DB = Sequel.sqlite # in-memory database, change later
DB.create_table :votes do
  primary_key :id
  DateTime :datetime
  foreign_key :topic_id, :topics
  foreign_key :user_id, :users
  TrueClass :vote, :null => false # boolean type
end

class Vote < Sequel::Model
  plugin :timestamps, :create => :datetime
  many_to_one :topic
  many_to_one :user
  many_to_many :modifiers
end

DB.create_table :modifiers_votes do
  primary_key :id
  foreign_key :vote_id, :votes
  foreign_key :modifier_id, :modifiers
end

DB.create_table :users do
  primary_key :id
  String :username, :null => false, :unique => true
  String :email, :null => false, :unique => true
  String :password_digest, :null => false
  String :twitter_id # if linked to Twitter
end

class User < Sequel::Model
  plugin :secure_password # https://github.com/mlen/sequel_secure_password
  one_to_many :votes
end

DB.create_table :topics do
  primary_key :id
  String :name
end

class Topic < Sequel::Model
  one_to_many :modifiers
end

DB.create_table :modifiers do
  primary_key :id
  String :name
  foreign_key :topic_id, :topics
end

class Modifier < Sequel::Model
  many_to_one :topic
  many_to_many :votes
end