Moving repetitive query building to centralized function
diff --git a/openstack/networking/v2/extensions/layer3/floatingips/requests.go b/openstack/networking/v2/extensions/layer3/floatingips/requests.go
index 36b4411..22a6cae 100644
--- a/openstack/networking/v2/extensions/layer3/floatingips/requests.go
+++ b/openstack/networking/v2/extensions/layer3/floatingips/requests.go
@@ -2,11 +2,9 @@
 
 import (
 	"fmt"
-	"strconv"
 
 	"github.com/racker/perigee"
 	"github.com/rackspace/gophercloud"
-	"github.com/rackspace/gophercloud/openstack/utils"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
@@ -16,52 +14,27 @@
 // sort by a particular network attribute. SortDir sets the direction, and is
 // either `asc' or `desc'. Marker and Limit are used for pagination.
 type ListOpts struct {
-	ID                string
-	FloatingNetworkID string
-	PortID            string
-	FixedIP           string
-	FloatingIP        string
-	TenantID          string
-	Limit             int
-	Marker            string
-	SortKey           string
-	SortDir           string
+	ID                string `q:"id"`
+	FloatingNetworkID string `q:"floating_network_id"`
+	PortID            string `q:"port_id"`
+	FixedIP           string `q:"fixed_ip_address"`
+	FloatingIP        string `q:"floating_ip_address"`
+	TenantID          string `q:"tenant_id"`
+	Limit             int    `q:"limit"`
+	Marker            string `q:"marker"`
+	SortKey           string `q:"sort_key"`
+	SortDir           string `q:"sort_dir"`
 }
 
 // List returns a Pager which allows you to iterate over a collection of
 // floating IP resources. It accepts a ListOpts struct, which allows you to
 // filter and sort the returned collection for greater efficiency.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
-	q := make(map[string]string)
-	if opts.ID != "" {
-		q["id"] = opts.ID
+	q, err := gophercloud.BuildQueryString(&opts)
+	if err != nil {
+		return pagination.Pager{Err: err}
 	}
-	if opts.FloatingNetworkID != "" {
-		q["floating_network_id"] = opts.FloatingNetworkID
-	}
-	if opts.FixedIP != "" {
-		q["fixed_ip_address"] = opts.FixedIP
-	}
-	if opts.FloatingIP != "" {
-		q["floating_ip_address"] = opts.FloatingIP
-	}
-	if opts.TenantID != "" {
-		q["tenant_id"] = opts.TenantID
-	}
-	if opts.Marker != "" {
-		q["marker"] = opts.Marker
-	}
-	if opts.Limit != 0 {
-		q["limit"] = strconv.Itoa(opts.Limit)
-	}
-	if opts.SortKey != "" {
-		q["sort_key"] = opts.SortKey
-	}
-	if opts.SortDir != "" {
-		q["sort_dir"] = opts.SortDir
-	}
-
-	u := rootURL(c) + utils.BuildQuery(q)
+	u := rootURL(c) + q.String()
 	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
 		return FloatingIPPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
 	})
diff --git a/openstack/networking/v2/extensions/layer3/routers/requests.go b/openstack/networking/v2/extensions/layer3/routers/requests.go
index f53f878..edbb366 100755
--- a/openstack/networking/v2/extensions/layer3/routers/requests.go
+++ b/openstack/networking/v2/extensions/layer3/routers/requests.go
@@ -2,11 +2,9 @@
 
 import (
 	"fmt"
-	"strconv"
 
 	"github.com/racker/perigee"
 	"github.com/rackspace/gophercloud"
-	"github.com/rackspace/gophercloud/openstack/utils"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
@@ -16,15 +14,15 @@
 // sort by a particular network attribute. SortDir sets the direction, and is
 // either `asc' or `desc'. Marker and Limit are used for pagination.
 type ListOpts struct {
-	ID           string
-	Name         string
-	AdminStateUp *bool
-	Status       string
-	TenantID     string
-	Limit        int
-	Marker       string
-	SortKey      string
-	SortDir      string
+	ID           string `q:"id"`
+	Name         string `q:"name"`
+	AdminStateUp *bool  `q:"admin_state_up"`
+	Status       string `q:"status"`
+	TenantID     string `q:"tenant_id"`
+	Limit        int    `q:"limit"`
+	Marker       string `q:"marker"`
+	SortKey      string `q:"sort_key"`
+	SortDir      string `q:"sort_dir"`
 }
 
 // List returns a Pager which allows you to iterate over a collection of
@@ -34,36 +32,11 @@
 // Default policy settings return only those routers that are owned by the
 // tenant who submits the request, unless an admin user submits the request.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
-	q := make(map[string]string)
-	if opts.ID != "" {
-		q["id"] = opts.ID
+	q, err := gophercloud.BuildQueryString(&opts)
+	if err != nil {
+		return pagination.Pager{Err: err}
 	}
-	if opts.Name != "" {
-		q["name"] = opts.Name
-	}
-	if opts.AdminStateUp != nil {
-		q["admin_state_up"] = strconv.FormatBool(*opts.AdminStateUp)
-	}
-	if opts.Status != "" {
-		q["status"] = opts.Status
-	}
-	if opts.TenantID != "" {
-		q["tenant_id"] = opts.TenantID
-	}
-	if opts.Marker != "" {
-		q["marker"] = opts.Marker
-	}
-	if opts.Limit != 0 {
-		q["limit"] = strconv.Itoa(opts.Limit)
-	}
-	if opts.SortKey != "" {
-		q["sort_key"] = opts.SortKey
-	}
-	if opts.SortDir != "" {
-		q["sort_dir"] = opts.SortDir
-	}
-
-	u := rootURL(c) + utils.BuildQuery(q)
+	u := rootURL(c) + q.String()
 	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
 		return RouterPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
 	})
diff --git a/openstack/networking/v2/extensions/lbaas/members/requests.go b/openstack/networking/v2/extensions/lbaas/members/requests.go
index 66302ab..d095706 100644
--- a/openstack/networking/v2/extensions/lbaas/members/requests.go
+++ b/openstack/networking/v2/extensions/lbaas/members/requests.go
@@ -1,11 +1,8 @@
 package members
 
 import (
-	"strconv"
-
 	"github.com/racker/perigee"
 	"github.com/rackspace/gophercloud"
-	"github.com/rackspace/gophercloud/openstack/utils"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
@@ -15,18 +12,18 @@
 // sort by a particular network attribute. SortDir sets the direction, and is
 // either `asc' or `desc'. Marker and Limit are used for pagination.
 type ListOpts struct {
-	Status       string
-	Weight       int
-	AdminStateUp *bool
-	TenantID     string
-	PoolID       string
-	Address      string
-	ProtocolPort int
-	ID           string
-	Limit        int
-	Marker       string
-	SortKey      string
-	SortDir      string
+	Status       string `q:"status"`
+	Weight       int    `q:"weight"`
+	AdminStateUp *bool  `q:"admin_state_up"`
+	TenantID     string `q:"tenant_id"`
+	PoolID       string `q:"pool_id"`
+	Address      string `q:"address"`
+	ProtocolPort int    `q:"protocol_port"`
+	ID           string `q:"id"`
+	Limit        int    `q:"limit"`
+	Marker       string `q:"marker"`
+	SortKey      string `q:"sort_key"`
+	SortDir      string `q:"sort_dir"`
 }
 
 // List returns a Pager which allows you to iterate over a collection of
@@ -36,47 +33,11 @@
 // Default policy settings return only those pools that are owned by the
 // tenant who submits the request, unless an admin user submits the request.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
-	q := make(map[string]string)
-
-	if opts.Status != "" {
-		q["status"] = opts.Status
+	q, err := gophercloud.BuildQueryString(&opts)
+	if err != nil {
+		return pagination.Pager{Err: err}
 	}
-	if opts.Weight != 0 {
-		q["weight"] = strconv.Itoa(opts.Weight)
-	}
-	if opts.PoolID != "" {
-		q["pool_id"] = opts.PoolID
-	}
-	if opts.Address != "" {
-		q["address"] = opts.Address
-	}
-	if opts.TenantID != "" {
-		q["tenant_id"] = opts.TenantID
-	}
-	if opts.AdminStateUp != nil {
-		q["admin_state_up"] = strconv.FormatBool(*opts.AdminStateUp)
-	}
-	if opts.ProtocolPort != 0 {
-		q["protocol_port"] = strconv.Itoa(opts.ProtocolPort)
-	}
-	if opts.ID != "" {
-		q["id"] = opts.ID
-	}
-	if opts.Marker != "" {
-		q["marker"] = opts.Marker
-	}
-	if opts.Limit != 0 {
-		q["limit"] = strconv.Itoa(opts.Limit)
-	}
-	if opts.SortKey != "" {
-		q["sort_key"] = opts.SortKey
-	}
-	if opts.SortDir != "" {
-		q["sort_dir"] = opts.SortDir
-	}
-
-	u := rootURL(c) + utils.BuildQuery(q)
-
+	u := rootURL(c) + q.String()
 	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
 		return MemberPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
 	})
diff --git a/openstack/networking/v2/extensions/lbaas/monitors/requests.go b/openstack/networking/v2/extensions/lbaas/monitors/requests.go
index a16f22f..9f63fc5 100644
--- a/openstack/networking/v2/extensions/lbaas/monitors/requests.go
+++ b/openstack/networking/v2/extensions/lbaas/monitors/requests.go
@@ -2,11 +2,9 @@
 
 import (
 	"fmt"
-	"strconv"
 
 	"github.com/racker/perigee"
 	"github.com/rackspace/gophercloud"
-	"github.com/rackspace/gophercloud/openstack/utils"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
@@ -16,21 +14,21 @@
 // sort by a particular network attribute. SortDir sets the direction, and is
 // either `asc' or `desc'. Marker and Limit are used for pagination.
 type ListOpts struct {
-	ID            string
-	TenantID      string
-	Type          string
-	Delay         int
-	Timeout       int
-	MaxRetries    int
-	HttpMethod    string
-	UrlPath       string
-	ExpectedCodes string
-	AdminStateUp  *bool
-	Status        string
-	Limit         int
-	Marker        string
-	SortKey       string
-	SortDir       string
+	ID            string `q:"id"`
+	TenantID      string `q:"tenant_id"`
+	Type          string `q:"type"`
+	Delay         int    `q:"delay"`
+	Timeout       int    `q:"timeout"`
+	MaxRetries    int    `q:"max_retries"`
+	HttpMethod    string `q:"http_method"`
+	UrlPath       string `q:"url_path"`
+	ExpectedCodes string `q:"expected_codes"`
+	AdminStateUp  *bool  `q:"admin_state_up"`
+	Status        string `q:"status"`
+	Limit         int    `q:"limit"`
+	Marker        string `q:"marker"`
+	SortKey       string `q:"sort_key"`
+	SortDir       string `q:"sort_dir"`
 }
 
 // List returns a Pager which allows you to iterate over a collection of
@@ -40,54 +38,11 @@
 // Default policy settings return only those routers that are owned by the
 // tenant who submits the request, unless an admin user submits the request.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
-	q := make(map[string]string)
-	if opts.ID != "" {
-		q["id"] = opts.ID
+	q, err := gophercloud.BuildQueryString(&opts)
+	if err != nil {
+		return pagination.Pager{Err: err}
 	}
-	if opts.TenantID != "" {
-		q["tenant_id"] = opts.TenantID
-	}
-	if opts.Type != "" {
-		q["type"] = opts.Type
-	}
-	if opts.Delay != 0 {
-		q["delay"] = strconv.Itoa(opts.Delay)
-	}
-	if opts.Timeout != 0 {
-		q["timeout"] = strconv.Itoa(opts.Timeout)
-	}
-	if opts.MaxRetries != 0 {
-		q["max_retries"] = strconv.Itoa(opts.MaxRetries)
-	}
-	if opts.HttpMethod != "" {
-		q["http_method"] = opts.HttpMethod
-	}
-	if opts.UrlPath != "" {
-		q["url_path"] = opts.UrlPath
-	}
-	if opts.AdminStateUp != nil {
-		q["admin_state_up"] = strconv.FormatBool(*opts.AdminStateUp)
-	}
-	if opts.Status != "" {
-		q["status"] = opts.Status
-	}
-	if opts.ExpectedCodes != "" {
-		q["expected_codes"] = opts.ExpectedCodes
-	}
-	if opts.Marker != "" {
-		q["marker"] = opts.Marker
-	}
-	if opts.Limit != 0 {
-		q["limit"] = strconv.Itoa(opts.Limit)
-	}
-	if opts.SortKey != "" {
-		q["sort_key"] = opts.SortKey
-	}
-	if opts.SortDir != "" {
-		q["sort_dir"] = opts.SortDir
-	}
-
-	u := rootURL(c) + utils.BuildQuery(q)
+	u := rootURL(c) + q.String()
 
 	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
 		return MonitorPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
diff --git a/openstack/networking/v2/extensions/lbaas/pools/requests.go b/openstack/networking/v2/extensions/lbaas/pools/requests.go
index c0098af..2688350 100644
--- a/openstack/networking/v2/extensions/lbaas/pools/requests.go
+++ b/openstack/networking/v2/extensions/lbaas/pools/requests.go
@@ -1,11 +1,8 @@
 package pools
 
 import (
-	"strconv"
-
 	"github.com/racker/perigee"
 	"github.com/rackspace/gophercloud"
-	"github.com/rackspace/gophercloud/openstack/utils"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
@@ -15,19 +12,19 @@
 // sort by a particular network attribute. SortDir sets the direction, and is
 // either `asc' or `desc'. Marker and Limit are used for pagination.
 type ListOpts struct {
-	Status       string
-	LBMethod     string
-	Protocol     string
-	SubnetID     string
-	TenantID     string
-	AdminStateUp *bool
-	Name         string
-	ID           string
-	VIPID        string
-	Limit        int
-	Marker       string
-	SortKey      string
-	SortDir      string
+	Status       string `q:"status"`
+	LBMethod     string `q:"lb_method"`
+	Protocol     string `q:"protocol"`
+	SubnetID     string `q:"subnet_id"`
+	TenantID     string `q:"tenant_id"`
+	AdminStateUp *bool  `q:"admin_state_up"`
+	Name         string `q:"name"`
+	ID           string `q:"id"`
+	VIPID        string `q:"vip_id"`
+	Limit        int    `q:"limit"`
+	Marker       string `q:"marker"`
+	SortKey      string `q:"sort_key"`
+	SortDir      string `q:"sort_dir"`
 }
 
 // List returns a Pager which allows you to iterate over a collection of
@@ -37,49 +34,11 @@
 // Default policy settings return only those pools that are owned by the
 // tenant who submits the request, unless an admin user submits the request.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
-	q := make(map[string]string)
-
-	if opts.Status != "" {
-		q["status"] = opts.Status
+	q, err := gophercloud.BuildQueryString(&opts)
+	if err != nil {
+		return pagination.Pager{Err: err}
 	}
-	if opts.LBMethod != "" {
-		q["lb_method"] = opts.LBMethod
-	}
-	if opts.Protocol != "" {
-		q["protocol"] = opts.Protocol
-	}
-	if opts.SubnetID != "" {
-		q["subnet_id"] = opts.SubnetID
-	}
-	if opts.TenantID != "" {
-		q["tenant_id"] = opts.TenantID
-	}
-	if opts.AdminStateUp != nil {
-		q["admin_state_up"] = strconv.FormatBool(*opts.AdminStateUp)
-	}
-	if opts.Name != "" {
-		q["name"] = opts.Name
-	}
-	if opts.ID != "" {
-		q["id"] = opts.ID
-	}
-	if opts.VIPID != "" {
-		q["vip_id"] = opts.VIPID
-	}
-	if opts.Marker != "" {
-		q["marker"] = opts.Marker
-	}
-	if opts.Limit != 0 {
-		q["limit"] = strconv.Itoa(opts.Limit)
-	}
-	if opts.SortKey != "" {
-		q["sort_key"] = opts.SortKey
-	}
-	if opts.SortDir != "" {
-		q["sort_dir"] = opts.SortDir
-	}
-
-	u := rootURL(c) + utils.BuildQuery(q)
+	u := rootURL(c) + q.String()
 	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
 		return PoolPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
 	})
diff --git a/openstack/networking/v2/extensions/lbaas/vips/requests.go b/openstack/networking/v2/extensions/lbaas/vips/requests.go
index f2d6ab7..8fadebf 100644
--- a/openstack/networking/v2/extensions/lbaas/vips/requests.go
+++ b/openstack/networking/v2/extensions/lbaas/vips/requests.go
@@ -2,11 +2,9 @@
 
 import (
 	"fmt"
-	"strconv"
 
 	"github.com/racker/perigee"
 	"github.com/rackspace/gophercloud"
-	"github.com/rackspace/gophercloud/openstack/utils"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
@@ -28,21 +26,21 @@
 // sort by a particular network attribute. SortDir sets the direction, and is
 // either `asc' or `desc'. Marker and Limit are used for pagination.
 type ListOpts struct {
-	ID              string
-	Name            string
-	AdminStateUp    *bool
-	Status          string
-	TenantID        string
-	SubnetID        string
-	Address         string
-	PortID          string
-	Protocol        string
-	ProtocolPort    int
-	ConnectionLimit int
-	Limit           int
-	Marker          string
-	SortKey         string
-	SortDir         string
+	ID              string `q:"id"`
+	Name            string `q:"name"`
+	AdminStateUp    *bool  `q:"admin_state_up"`
+	Status          string `q:"status"`
+	TenantID        string `q:"tenant_id"`
+	SubnetID        string `q:"subnet_id"`
+	Address         string `q:"address"`
+	PortID          string `q:"port_id"`
+	Protocol        string `q:"protocol"`
+	ProtocolPort    int    `q:"protocol_port"`
+	ConnectionLimit int    `q:"connection_limit"`
+	Limit           int    `q:"limit"`
+	Marker          string `q:"marker"`
+	SortKey         string `q:"sort_key"`
+	SortDir         string `q:"sort_dir"`
 }
 
 // List returns a Pager which allows you to iterate over a collection of
@@ -52,55 +50,11 @@
 // Default policy settings return only those routers that are owned by the
 // tenant who submits the request, unless an admin user submits the request.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
-	q := make(map[string]string)
-	if opts.ID != "" {
-		q["id"] = opts.ID
+	q, err := gophercloud.BuildQueryString(&opts)
+	if err != nil {
+		return pagination.Pager{Err: err}
 	}
-	if opts.Name != "" {
-		q["name"] = opts.Name
-	}
-	if opts.AdminStateUp != nil {
-		q["admin_state_up"] = strconv.FormatBool(*opts.AdminStateUp)
-	}
-	if opts.Status != "" {
-		q["status"] = opts.Status
-	}
-	if opts.TenantID != "" {
-		q["tenant_id"] = opts.TenantID
-	}
-	if opts.SubnetID != "" {
-		q["subnet_id"] = opts.SubnetID
-	}
-	if opts.Address != "" {
-		q["address"] = opts.Address
-	}
-	if opts.PortID != "" {
-		q["port_id"] = opts.PortID
-	}
-	if opts.Protocol != "" {
-		q["protocol"] = opts.Protocol
-	}
-	if opts.ProtocolPort != 0 {
-		q["protocol_port"] = strconv.Itoa(opts.ProtocolPort)
-	}
-	if opts.ConnectionLimit != 0 {
-		q["connection_limit"] = strconv.Itoa(opts.ConnectionLimit)
-	}
-	if opts.Marker != "" {
-		q["marker"] = opts.Marker
-	}
-	if opts.Limit != 0 {
-		q["limit"] = strconv.Itoa(opts.Limit)
-	}
-	if opts.SortKey != "" {
-		q["sort_key"] = opts.SortKey
-	}
-	if opts.SortDir != "" {
-		q["sort_dir"] = opts.SortDir
-	}
-
-	u := rootURL(c) + utils.BuildQuery(q)
-
+	u := rootURL(c) + q.String()
 	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
 		return VIPPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
 	})
diff --git a/openstack/networking/v2/networks/requests.go b/openstack/networking/v2/networks/requests.go
index 9b52c8d..8b28291 100644
--- a/openstack/networking/v2/networks/requests.go
+++ b/openstack/networking/v2/networks/requests.go
@@ -2,11 +2,9 @@
 
 import (
 	"fmt"
-	"strconv"
 
 	"github.com/racker/perigee"
 	"github.com/rackspace/gophercloud"
-	"github.com/rackspace/gophercloud/openstack/utils"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
@@ -23,16 +21,16 @@
 // by a particular network attribute. SortDir sets the direction, and is either
 // `asc' or `desc'. Marker and Limit are used for pagination.
 type ListOpts struct {
-	Status       string
-	Name         string
-	AdminStateUp *bool
-	TenantID     string
-	Shared       *bool
-	ID           string
-	Marker       string
-	Limit        int
-	SortKey      string
-	SortDir      string
+	Status       string `q:"status"`
+	Name         string `q:"name"`
+	AdminStateUp *bool  `q:"admin_state_up"`
+	TenantID     string `q:"tenant_id"`
+	Shared       *bool  `q:"shared"`
+	ID           string `q:"id"`
+	Marker       string `q:"marker"`
+	Limit        int    `q:"limit"`
+	SortKey      string `q:"sort_key"`
+	SortDir      string `q:"sort_dir"`
 }
 
 // List returns a Pager which allows you to iterate over a collection of
@@ -40,39 +38,11 @@
 // the returned collection for greater efficiency.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 	// Build query parameters
-	q := make(map[string]string)
-	if opts.Status != "" {
-		q["status"] = opts.Status
+	q, err := gophercloud.BuildQueryString(&opts)
+	if err != nil {
+		return pagination.Pager{Err: err}
 	}
-	if opts.Name != "" {
-		q["name"] = opts.Name
-	}
-	if opts.AdminStateUp != nil {
-		q["admin_state_up"] = strconv.FormatBool(*opts.AdminStateUp)
-	}
-	if opts.TenantID != "" {
-		q["tenant_id"] = opts.TenantID
-	}
-	if opts.Shared != nil {
-		q["shared"] = strconv.FormatBool(*opts.Shared)
-	}
-	if opts.ID != "" {
-		q["id"] = opts.ID
-	}
-	if opts.Marker != "" {
-		q["marker"] = opts.Marker
-	}
-	if opts.Limit != 0 {
-		q["limit"] = strconv.Itoa(opts.Limit)
-	}
-	if opts.SortKey != "" {
-		q["sort_key"] = opts.SortKey
-	}
-	if opts.SortDir != "" {
-		q["sort_dir"] = opts.SortDir
-	}
-
-	u := listURL(c) + utils.BuildQuery(q)
+	u := listURL(c) + q.String()
 	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
 		return NetworkPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
 	})
diff --git a/openstack/networking/v2/ports/requests.go b/openstack/networking/v2/ports/requests.go
index da738d2..6928d8f 100644
--- a/openstack/networking/v2/ports/requests.go
+++ b/openstack/networking/v2/ports/requests.go
@@ -1,11 +1,8 @@
 package ports
 
 import (
-	"strconv"
-
 	"github.com/racker/perigee"
 	"github.com/rackspace/gophercloud"
-	"github.com/rackspace/gophercloud/openstack/utils"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
@@ -15,22 +12,19 @@
 // by a particular port attribute. SortDir sets the direction, and is either
 // `asc' or `desc'. Marker and Limit are used for pagination.
 type ListOpts struct {
-	Status          string
-	Name            string
-	AdminStateUp    *bool
-	NetworkID       string
-	TenantID        string
-	DeviceOwner     string
-	MACAddress      string
-	ID              string
-	DeviceID        string
-	BindingHostID   string
-	BindingVIFType  string
-	BindingVNICType string
-	Limit           int
-	Marker          string
-	SortKey         string
-	SortDir         string
+	Status       string `q:"status"`
+	Name         string `q:"name"`
+	AdminStateUp *bool  `q:"admin_state_up"`
+	NetworkID    string `q:"network_id"`
+	TenantID     string `q:"tenant_id"`
+	DeviceOwner  string `q:"device_owner"`
+	MACAddress   string `q:"mac_address"`
+	ID           string `q:"id"`
+	DeviceID     string `q:"device_id"`
+	Limit        int    `q:"limit"`
+	Marker       string `q:"marker"`
+	SortKey      string `q:"sort_key"`
+	SortDir      string `q:"sort_dir"`
 }
 
 // List returns a Pager which allows you to iterate over a collection of
@@ -42,60 +36,12 @@
 // administrative rights.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 	// Build query parameters
-	q := make(map[string]string)
-	if opts.Status != "" {
-		q["status"] = opts.Status
+	q, err := gophercloud.BuildQueryString(&opts)
+	if err != nil {
+		return pagination.Pager{Err: err}
 	}
-	if opts.Name != "" {
-		q["name"] = opts.Name
-	}
-	if opts.AdminStateUp != nil {
-		q["admin_state_up"] = strconv.FormatBool(*opts.AdminStateUp)
-	}
-	if opts.NetworkID != "" {
-		q["network_id"] = opts.NetworkID
-	}
-	if opts.TenantID != "" {
-		q["tenant_id"] = opts.TenantID
-	}
-	if opts.DeviceOwner != "" {
-		q["device_owner"] = opts.DeviceOwner
-	}
-	if opts.MACAddress != "" {
-		q["mac_address"] = opts.MACAddress
-	}
-	if opts.ID != "" {
-		q["id"] = opts.ID
-	}
-	if opts.DeviceID != "" {
-		q["device_id"] = opts.DeviceID
-	}
-	if opts.BindingHostID != "" {
-		q["binding:host_id"] = opts.BindingHostID
-	}
-	if opts.BindingVIFType != "" {
-		q["binding:vif_type"] = opts.BindingVIFType
-	}
-	if opts.BindingVNICType != "" {
-		q["binding:vnic_type"] = opts.BindingVNICType
-	}
-	if opts.NetworkID != "" {
-		q["network_id"] = opts.NetworkID
-	}
-	if opts.Limit != 0 {
-		q["limit"] = strconv.Itoa(opts.Limit)
-	}
-	if opts.Marker != "" {
-		q["marker"] = opts.Marker
-	}
-	if opts.SortKey != "" {
-		q["sort_key"] = opts.SortKey
-	}
-	if opts.SortDir != "" {
-		q["sort_dir"] = opts.SortDir
-	}
+	u := listURL(c) + q.String()
 
-	u := listURL(c) + utils.BuildQuery(q)
 	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
 		return PortPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
 	})
diff --git a/openstack/networking/v2/subnets/requests.go b/openstack/networking/v2/subnets/requests.go
index ee5631d..092c914 100644
--- a/openstack/networking/v2/subnets/requests.go
+++ b/openstack/networking/v2/subnets/requests.go
@@ -3,7 +3,6 @@
 import (
 	"github.com/racker/perigee"
 	"github.com/rackspace/gophercloud"
-	"github.com/rackspace/gophercloud/openstack/utils"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
@@ -36,9 +35,13 @@
 // administrative rights.
 func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
 	// Build query parameters
+	query, err := gophercloud.BuildQueryString(&opts)
+	if err != nil {
+		return pagination.Pager{Err: err}
+	}
+	url := listURL(c) + query.String()
 
-	u := listURL(c) + utils.BuildQuery(q)
-	return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
+	return pagination.NewPager(c, url, func(r pagination.LastHTTPResponse) pagination.Page {
 		return SubnetPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
 	})
 }