diff --git a/doc/en/user/source/data/sqlview.rst b/doc/en/user/source/data/sqlview.rst
index 24dd9b9..816c539 100644
--- a/doc/en/user/source/data/sqlview.rst
+++ b/doc/en/user/source/data/sqlview.rst
@@ -81,6 +81,8 @@ In order to get all the states having between 2 and 5 millions inhabintants the
 .. figure:: images/sqlview-2m-5m.png
    :align: center
    
+   
+The ``viewparams`` can be also specified on a layer per layer basis using the syntax ``viewparams=l1p1:v1;l1p2:v2,l2p1:v1;l2p2:v2,...``, that is, separating each layer map with a comma. In this case the number of parameter maps must match the number of layers (or feature types) included in the request.
 
 Parameters and validation
 -------------------------
diff --git a/src/ows/src/main/java/org/geoserver/ows/kvp/ViewParamsKvpParser.java b/src/ows/src/main/java/org/geoserver/ows/kvp/ViewParamsKvpParser.java
new file mode 100644
index 0000000..03d2677
--- /dev/null
+++ b/src/ows/src/main/java/org/geoserver/ows/kvp/ViewParamsKvpParser.java
@@ -0,0 +1,59 @@
+/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
+ * This code is licensed under the GPL 2.0 license, availible at the root
+ * application directory.
+ */
+package org.geoserver.ows.kvp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.geoserver.ows.KvpParser;
+import org.geoserver.ows.util.KvpUtils;
+import org.geoserver.platform.GeoServerExtensions;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * Parses view parameters which are of the form:
+ * 
+ * <pre>VIEWPARAMS=opt1:val1,val2;opt2:val1;opt3:...[,opt1:val1,val2;opt2:val1;opt3:...]</pre>
+ *
+ * @see FormatOptionsKvpParser
+ */
+public class ViewParamsKvpParser extends KvpParser implements ApplicationContextAware {
+    /**
+     * application context used to lookup KvpParsers
+     */
+    ApplicationContext applicationContext;
+
+    public ViewParamsKvpParser() {
+        super("viewparams", List.class);
+    }
+ 
+    public void setApplicationContext(ApplicationContext applicationContext)
+        throws BeansException {
+        this.applicationContext = applicationContext;
+    }
+
+    public Object parse(String value) throws Exception {
+    	List ret = new ArrayList();
+        List parsers = GeoServerExtensions.extensions(KvpParser.class, applicationContext);
+        KvpParser formatOptionsParser = null;
+        for (Object o : parsers) {
+            KvpParser parser = (KvpParser) o;
+            if ( parser.getKey().equalsIgnoreCase("format_options") ) {
+            	formatOptionsParser = parser;
+            	break;
+            }
+        }
+        if (formatOptionsParser == null) {
+        	throw new IllegalStateException("Missing format options parser.");
+        }
+        for (String kvp : KvpUtils.escapedTokens(value, ',')) {
+        	ret.add(formatOptionsParser.parse(kvp));
+        }
+
+        return ret;
+    }
+}
diff --git a/src/wfs/src/main/java/applicationContext.xml b/src/wfs/src/main/java/applicationContext.xml
index d474fbf..de93008 100644
--- a/src/wfs/src/main/java/applicationContext.xml
+++ b/src/wfs/src/main/java/applicationContext.xml
@@ -253,8 +253,7 @@
     <bean id="charsetKvpParser" class="org.geoserver.ows.kvp.CharsetKVPParser">
         <constructor-arg value="charset"/>
     </bean>
-  <bean id="wfsSqlViewKvpParser" class="org.geoserver.ows.kvp.FormatOptionsKvpParser">
-    <constructor-arg index="0" value="viewParams"/>
+  <bean id="wfsSqlViewKvpParser" class="org.geoserver.ows.kvp.ViewParamsKvpParser">
     <property name="service" value="WFS"/>
   </bean>
 
diff --git a/src/wfs/src/main/java/org/geoserver/wfs/GetFeature.java b/src/wfs/src/main/java/org/geoserver/wfs/GetFeature.java
index 98af400..4cccaed 100644
--- a/src/wfs/src/main/java/org/geoserver/wfs/GetFeature.java
+++ b/src/wfs/src/main/java/org/geoserver/wfs/GetFeature.java
@@ -8,11 +8,9 @@ import java.io.IOException;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Calendar;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Set;
-import java.util.Stack;
+import java.util.Map;
 import java.util.logging.Logger;
 
 import javax.xml.namespace.QName;
@@ -33,8 +31,8 @@ import org.geoserver.catalog.Catalog;
 import org.geoserver.catalog.FeatureTypeInfo;
 import org.geoserver.catalog.NamespaceInfo;
 import org.geotools.data.DataUtilities;
-import org.geotools.data.Query;
 import org.geotools.data.FeatureSource;
+import org.geotools.data.Query;
 import org.geotools.data.simple.SimpleFeatureCollection;
 import org.geotools.factory.Hints;
 import org.geotools.feature.FeatureCollection;
@@ -51,11 +49,8 @@ import org.geotools.xml.EMFUtils;
 import org.opengis.feature.Feature;
 import org.opengis.feature.simple.SimpleFeatureType;
 import org.opengis.feature.type.AttributeDescriptor;
-import org.opengis.feature.type.ComplexType;
 import org.opengis.feature.type.FeatureType;
 import org.opengis.feature.type.GeometryDescriptor;
-import org.opengis.feature.type.Name;
-import org.opengis.feature.type.PropertyDescriptor;
 import org.opengis.filter.Filter;
 import org.opengis.filter.FilterFactory2;
 import org.opengis.filter.expression.ExpressionVisitor;
@@ -175,9 +170,14 @@ public class GetFeature {
         // take into consideration the wfs max features
         int maxFeatures = Math.min(request.getMaxFeatures().intValue(),
                 wfs.getMaxFeatures());
+        
+        // grab the view params is any
+        List<Map<String, String>> viewParams = null;
+        if(request.getMetadata() != null) {
+            viewParams = (List<Map<String, String>>) request.getMetadata().get(SQL_VIEW_PARAMS);
+        }
 
         int count = 0; //should probably be long
-
         List results = new ArrayList();
         try {
             for (int i = 0; (i < request.getQuery().size()) && (count < maxFeatures); i++) {
@@ -364,7 +364,8 @@ public class GetFeature {
                 int queryMaxFeatures = maxFeatures - count;
                 if(meta.getMaxFeatures() > 0 && meta.getMaxFeatures() < queryMaxFeatures)
                     queryMaxFeatures = meta.getMaxFeatures();
-                org.geotools.data.Query gtQuery = toDataQuery(query, queryMaxFeatures, source, request, allPropNames);
+                Map<String, String> viewParam = viewParams != null ? viewParams.get(i) : null;
+                org.geotools.data.Query gtQuery = toDataQuery(query, queryMaxFeatures, source, request, allPropNames, viewParam);
                 
                 LOGGER.fine("Query is " + query + "\n To gt2: " + gtQuery);
 
@@ -493,7 +494,8 @@ public class GetFeature {
      *
      */
     public org.geotools.data.Query toDataQuery(QueryType query, int maxFeatures,
-        FeatureSource<? extends FeatureType, ? extends Feature> source, GetFeatureType request, List<PropertyName> props) throws WFSException {
+        FeatureSource<? extends FeatureType, ? extends Feature> source, GetFeatureType request, 
+        List<PropertyName> props, Map<String, String> viewParams) throws WFSException {
         
         String wfsVersion = request.getVersion();
         
@@ -593,8 +595,8 @@ public class GetFeature {
         hints.put(Hints.JTS_COORDINATE_SEQUENCE_FACTORY, new LiteCoordinateSequenceFactory());
         
         // check for sql view parameters
-        if(request.getMetadata() != null && request.getMetadata().containsKey(SQL_VIEW_PARAMS)) {
-            hints.put(Hints.VIRTUAL_TABLE_PARAMETERS, request.getMetadata().get(SQL_VIEW_PARAMS));
+        if(viewParams != null) {
+            hints.put(Hints.VIRTUAL_TABLE_PARAMETERS, viewParams);
         }
         
         //currently only used by app-schema, produce mandatory properties
diff --git a/src/wfs/src/main/java/org/geoserver/wfs/kvp/GetFeatureKvpRequestReader.java b/src/wfs/src/main/java/org/geoserver/wfs/kvp/GetFeatureKvpRequestReader.java
index dd2c8f9..1ec8b4a 100644
--- a/src/wfs/src/main/java/org/geoserver/wfs/kvp/GetFeatureKvpRequestReader.java
+++ b/src/wfs/src/main/java/org/geoserver/wfs/kvp/GetFeatureKvpRequestReader.java
@@ -24,6 +24,7 @@ import org.eclipse.emf.ecore.EObject;
 import org.geoserver.catalog.Catalog;
 import org.geoserver.catalog.FeatureTypeInfo;
 import org.geoserver.catalog.NamespaceInfo;
+import org.geoserver.platform.ServiceException;
 import org.geoserver.wfs.GetFeature;
 import org.geoserver.wfs.WFSException;
 import org.geotools.geometry.jts.ReferencedEnvelope;
@@ -258,7 +259,27 @@ public class GetFeatureKvpRequestReader extends WFSKvpRequestReader {
             if(gft.getMetadata() == null) {
                 gft.setMetadata(new HashMap());
             } 
-            gft.getMetadata().put(GetFeature.SQL_VIEW_PARAMS, kvp.get("viewParams"));
+            
+            // fan out over all layers if necessary
+            List<Map<String, String>> viewParams = (List<Map<String, String>>) kvp.get("viewParams");
+            if(viewParams.size() > 0) {
+                int layerCount = gft.getQuery().size();
+                
+                // if we have just one replicate over all layers
+                if(viewParams.size() == 1 && layerCount > 1) {
+                    List<Map<String, String>> replacement = new ArrayList<Map<String,String>>();
+                    for (int i = 0; i < layerCount; i++) {
+                        replacement.add(viewParams.get(0));
+                    }
+                    viewParams = replacement;
+                } else if(viewParams.size() != layerCount) {
+                    String msg = layerCount + " feature types requested, but found " + viewParams.size()
+                    + " view params specified. ";
+                    throw new ServiceException(msg, getClass().getName());
+                }
+            }
+            
+            gft.getMetadata().put(GetFeature.SQL_VIEW_PARAMS, viewParams);
         }
 
         return request;
diff --git a/src/wfs/src/test/java/org/geoserver/wfs/kvp/GetFeatureKvpRequestReaderTest.java b/src/wfs/src/test/java/org/geoserver/wfs/kvp/GetFeatureKvpRequestReaderTest.java
index 38ccb1e..c3ba4a4 100644
--- a/src/wfs/src/test/java/org/geoserver/wfs/kvp/GetFeatureKvpRequestReaderTest.java
+++ b/src/wfs/src/test/java/org/geoserver/wfs/kvp/GetFeatureKvpRequestReaderTest.java
@@ -152,9 +152,58 @@ public class GetFeatureKvpRequestReaderTest extends KvpRequestReaderTestSupport
         Object read = reader.read(req, parsed, raw);
         GetFeatureType parsedReq = (GetFeatureType) read;
         assertEquals(1, parsedReq.getMetadata().size());
-        Map viewParams = (Map) parsedReq.getMetadata().get(GetFeature.SQL_VIEW_PARAMS);
+        List<Map<String, String>> viewParams = (List<Map<String, String>>) parsedReq.getMetadata().get(GetFeature.SQL_VIEW_PARAMS);
+        assertEquals(1, viewParams.size());
+        Map<String, String> vp1 = viewParams.get(0);
+        assertEquals("WHERE PERSONS > 1000000", vp1.get("where"));
+        assertEquals("ABCD", vp1.get("str"));
+    }
+    
+    public void testViewParamsMulti() throws Exception {
+        Map<String, String> raw = new HashMap<String, String>();
+        raw.put("service", "WFS");
+        raw.put("version", "1.1.0");
+        raw.put("request", "GetFeature");
+        raw.put("typeName", getLayerId(MockData.STREAMS) + "," + getLayerId(MockData.BASIC_POLYGONS));
+        raw.put("viewParams", "where:WHERE PERSONS > 1000000;str:ABCD,where:WHERE PERSONS > 10;str:FOO");
+
+        Map<String, Object> parsed = parseKvp(raw);
+
+        GetFeatureType req = WfsFactory.eINSTANCE.createGetFeatureType();
+        Object read = reader.read(req, parsed, raw);
+        GetFeatureType parsedReq = (GetFeatureType) read;
+        assertEquals(1, parsedReq.getMetadata().size());
+        List<Map<String, String>> viewParams = (List<Map<String, String>>) parsedReq.getMetadata().get(GetFeature.SQL_VIEW_PARAMS);
+        assertEquals(2, viewParams.size());
+        Map<String, String> vp1 = viewParams.get(0);
+        assertEquals("WHERE PERSONS > 1000000", vp1.get("where"));
+        assertEquals("ABCD", vp1.get("str"));
+        Map<String, String> vp2 = viewParams.get(1);
+        assertEquals("WHERE PERSONS > 10", vp2.get("where"));
+        assertEquals("FOO", vp2.get("str"));
+    }
+    
+    public void testViewParamsFanOut() throws Exception {
+        Map<String, String> raw = new HashMap<String, String>();
+        raw.put("service", "WFS");
+        raw.put("version", "1.1.0");
+        raw.put("request", "GetFeature");
+        raw.put("typeName", getLayerId(MockData.STREAMS) + "," + getLayerId(MockData.BASIC_POLYGONS));
+        raw.put("viewParams", "where:WHERE PERSONS > 1000000;str:ABCD");
+
+        Map<String, Object> parsed = parseKvp(raw);
+
+        GetFeatureType req = WfsFactory.eINSTANCE.createGetFeatureType();
+        Object read = reader.read(req, parsed, raw);
+        GetFeatureType parsedReq = (GetFeatureType) read;
+        assertEquals(1, parsedReq.getMetadata().size());
+        List<Map<String, String>> viewParams = (List<Map<String, String>>) parsedReq.getMetadata().get(GetFeature.SQL_VIEW_PARAMS);
         assertEquals(2, viewParams.size());
-        assertEquals("WHERE PERSONS > 1000000", viewParams.get("where"));
-        assertEquals("ABCD", viewParams.get("str"));
+        Map<String, String> vp1 = viewParams.get(0);
+        assertEquals("WHERE PERSONS > 1000000", vp1.get("where"));
+        assertEquals("ABCD", vp1.get("str"));
+        Map<String, String> vp2 = viewParams.get(1);
+        assertEquals("WHERE PERSONS > 1000000", vp2.get("where"));
+        assertEquals("ABCD", vp2.get("str"));
     }
 }
diff --git a/src/wms/src/main/java/applicationContext.xml b/src/wms/src/main/java/applicationContext.xml
index 1aac6be..d906f99 100644
--- a/src/wms/src/main/java/applicationContext.xml
+++ b/src/wms/src/main/java/applicationContext.xml
@@ -198,8 +198,7 @@
  	<bean id="wmsEnviromentKvpParser" class="org.geoserver.ows.kvp.FormatOptionsKvpParser">
  		<constructor-arg index="0" value="env"/>
  	</bean>
-  <bean id="wmsSqlViewKvpParser" class="org.geoserver.ows.kvp.FormatOptionsKvpParser">
-    <constructor-arg index="0" value="viewParams"/>
+  <bean id="wmsSqlViewKvpParser" class="org.geoserver.ows.kvp.ViewParamsKvpParser">
     <!-- cannot set the service or it won't work for the reflectors -->
   </bean>
  	<bean id="bgColorKvpParser" class="org.geoserver.wms.kvp.ColorKvpParser">
diff --git a/src/wms/src/main/java/org/geoserver/wms/GetFeatureInfo.java b/src/wms/src/main/java/org/geoserver/wms/GetFeatureInfo.java
index 5e80e79..437577e 100644
--- a/src/wms/src/main/java/org/geoserver/wms/GetFeatureInfo.java
+++ b/src/wms/src/main/java/org/geoserver/wms/GetFeatureInfo.java
@@ -126,7 +126,7 @@ public class GetFeatureInfo {
         } finally {
             EnvFunction.clearLocalValues();
         }
-
+        
         FeatureCollectionType ret = buildResults(results);
 
         return ret;
@@ -196,7 +196,7 @@ public class GetFeatureInfo {
         final int x = request.getXPixel();
         final int y = request.getYPixel();
         final int buffer = request.getGetMapRequest().getBuffer();
-        final Map<String, String> viewParams = request.getGetMapRequest().getViewParams();
+        final List<Map<String, String>> viewParams = request.getGetMapRequest().getViewParams();
         final GetMapRequest getMapReq = request.getGetMapRequest();
         final CoordinateReferenceSystem requestedCRS = getMapReq.getCrs(); // optional, may be null
 
@@ -232,7 +232,8 @@ public class GetFeatureInfo {
 
             FeatureCollection collection = null;
             if (layer.getType() == MapLayerInfo.TYPE_VECTOR) {
-                collection = identifyVectorLayer(filters, x, y, buffer, viewParams,
+                final Map<String, String> viewParam = viewParams != null ? viewParams.get(i) : null;
+                collection = identifyVectorLayer(filters, x, y, buffer, viewParam,
                         requestedCRS, width, height, bbox, ff, results, i, layer, rules, maxFeatures);
 
             } else if (layer.getType() == MapLayerInfo.TYPE_RASTER) {
@@ -789,4 +790,4 @@ public class GetFeatureInfo {
         return at;
     }
 
-}
+}
\ No newline at end of file
diff --git a/src/wms/src/main/java/org/geoserver/wms/GetMap.java b/src/wms/src/main/java/org/geoserver/wms/GetMap.java
index c7284f9..ad384cc 100644
--- a/src/wms/src/main/java/org/geoserver/wms/GetMap.java
+++ b/src/wms/src/main/java/org/geoserver/wms/GetMap.java
@@ -13,6 +13,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.TimeZone;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -141,6 +142,8 @@ public class GetMap {
         }
 
         final List<MapLayerInfo> layers = request.getLayers();
+        final List<Map<String, String>> viewParams = request.getViewParams();
+        
         final Style[] styles = request.getStyles().toArray(new Style[] {});
         final Filter[] filters = buildLayersFilters(request.getFilter(), layers);
 
@@ -260,10 +263,9 @@ public class GetMap {
                 final Query definitionQuery = new Query(source.getSchema().getName().getLocalPart());
                 definitionQuery.setVersion(featureVersion);
                 definitionQuery.setFilter(layerFilter);
-                if (request.getViewParams() != null && request.getViewParams().size() > 0) {
-                    definitionQuery.setHints(new Hints(Hints.VIRTUAL_TABLE_PARAMETERS, request
-                            .getViewParams()));
-                }
+            	if (viewParams != null) {
+                    definitionQuery.setHints(new Hints(Hints.VIRTUAL_TABLE_PARAMETERS, viewParams.get(i)));
+            	}
 
                 // check for startIndex + offset
                 final Integer startIndex = request.getStartIndex();
diff --git a/src/wms/src/main/java/org/geoserver/wms/GetMapRequest.java b/src/wms/src/main/java/org/geoserver/wms/GetMapRequest.java
index 956cc9a..8546740 100644
--- a/src/wms/src/main/java/org/geoserver/wms/GetMapRequest.java
+++ b/src/wms/src/main/java/org/geoserver/wms/GetMapRequest.java
@@ -49,7 +49,7 @@ public class GetMapRequest extends WMSRequest {
     private Map /* <String,Object> */env = new HashMap();
 
     /** sql view parameters */
-    private Map<String, String> viewParams = new HashMap<String, String>();
+    private List<Map<String, String>> viewParams = null;
 
     private Map<String, String> httpRequestHeaders;
 
@@ -110,7 +110,7 @@ public class GetMapRequest extends WMSRequest {
      * 
      * @return
      */
-    public Map<String, String> getViewParams() {
+    public List<Map<String, String>> getViewParams() {
         return viewParams;
     }
 
@@ -382,7 +382,7 @@ public class GetMapRequest extends WMSRequest {
      * 
      * @param viewParams
      */
-    public void setViewParams(Map<String, String> viewParams) {
+    public void setViewParams(List<Map<String, String>> viewParams) {
         this.viewParams = viewParams;
     }
 
diff --git a/src/wms/src/main/java/org/geoserver/wms/WMSRequests.java b/src/wms/src/main/java/org/geoserver/wms/WMSRequests.java
index 9d9ec3e..d7f5a52 100644
--- a/src/wms/src/main/java/org/geoserver/wms/WMSRequests.java
+++ b/src/wms/src/main/java/org/geoserver/wms/WMSRequests.java
@@ -424,19 +424,18 @@ public class WMSRequests {
     /**
      * Encodes a map of formation options to be used as the value in a kvp.
      * 
-     * @param formatOptions
-     *            The map of formation options.
+     * @param formatOptions The map of formation options.
+     * @param sb StringBuffer to append to.
      * 
      * @return A string of the form 'key1:value1,value2;key2:value1;...', or the empty string if the
      *         formatOptions map is empty.
      * 
      */
-    public static String encodeFormatOptions(Map formatOptions) {
+    public static void encodeFormatOptions(Map formatOptions, StringBuffer sb) {
         if (formatOptions == null || formatOptions.isEmpty()) {
-            return "";
+            return;
         }
 
-        StringBuffer sb = new StringBuffer();
         for (Iterator e = formatOptions.entrySet().iterator(); e.hasNext();) {
             Map.Entry entry = (Map.Entry) e.next();
             String key = (String) entry.getKey();
@@ -465,6 +464,50 @@ public class WMSRequests {
         }
 
         sb.setLength(sb.length());
+    }
+
+    /**
+     * Encodes a map of format options to be used as the value in a kvp.
+     * 
+     * @param formatOptions The map of format options.
+     * 
+     * @return A string of the form 'key1:value1,value2;key2:value1;...', or the empty string if the
+     *         formatOptions map is empty.
+     * 
+     */
+    public static String encodeFormatOptions(Map formatOptions) {
+    	StringBuffer sb = new StringBuffer();
+    	encodeFormatOptions(formatOptions, sb);
+    	return sb.toString();
+    }
+    
+    /**
+     * Encodes a list of format option maps to be used as the value in a kvp.
+     * 
+     * @param formatOptions The list of formation option maps.
+     * @param sb StringBuffer to append to.
+     * 
+     * @return A string of the form 'key1.1:value1.1,value1.2;key1.2:value1.1;...[,key2.1:value2.1,value2.2;key2.2:value2.1]', 
+     * 	or the empty string if the formatOptions list is empty.
+     * 
+     */
+    public static String encodeFormatOptions(List<Map<String, String>> formatOptions) {
+        if (formatOptions == null || formatOptions.isEmpty()) {
+            return "";
+        }
+        
+        StringBuffer sb = new StringBuffer();
+        boolean first = true;
+        for (Map<String, String> map : formatOptions) {
+        	if (first) {
+        		first = false;
+        	} else {
+                sb.append(",");
+        	}
+            encodeFormatOptions(map, sb);
+        }
+
+        sb.setLength(sb.length());
         return sb.toString();
     }
 
diff --git a/src/wms/src/main/java/org/geoserver/wms/map/GetMapKvpRequestReader.java b/src/wms/src/main/java/org/geoserver/wms/map/GetMapKvpRequestReader.java
index 43eafd5..21e0c06 100644
--- a/src/wms/src/main/java/org/geoserver/wms/map/GetMapKvpRequestReader.java
+++ b/src/wms/src/main/java/org/geoserver/wms/map/GetMapKvpRequestReader.java
@@ -396,6 +396,25 @@ public class GetMapKvpRequestReader extends KvpRequestReader implements HttpServ
                 throw new ServiceException(msg, getClass().getName());
             }
         }
+        
+        // check the view params
+        List<Map<String, String>> viewParams = getMap.getViewParams();
+        if(viewParams != null && viewParams.size() > 0) {
+            int layerCount = getMap.getLayers().size();
+            
+            // if we have just one replicate over all layers
+            if(viewParams.size() == 1 && layerCount > 1) {
+                List<Map<String, String>> replacement = new ArrayList<Map<String,String>>();
+                for (int i = 0; i < layerCount; i++) {
+                    replacement.add(viewParams.get(0));
+                }
+                getMap.setViewParams(replacement);
+            } else if(viewParams.size() != layerCount) {
+                String msg = layerCount + " layers requested, but found " + viewParams.size()
+                + " view params specified. ";
+                throw new ServiceException(msg, getClass().getName());
+            }
+        }
 
         return getMap;
     }
diff --git a/src/wms/src/test/java/org/geoserver/wms/map/GetMapKvpRequestReaderTest.java b/src/wms/src/test/java/org/geoserver/wms/map/GetMapKvpRequestReaderTest.java
index 078d3f7..309c857 100644
--- a/src/wms/src/test/java/org/geoserver/wms/map/GetMapKvpRequestReaderTest.java
+++ b/src/wms/src/test/java/org/geoserver/wms/map/GetMapKvpRequestReaderTest.java
@@ -467,9 +467,63 @@ public class GetMapKvpRequestReaderTest extends KvpRequestReaderTestSupport {
         GetMapRequest request = (GetMapRequest) reader.createRequest();
         request = (GetMapRequest) reader.read(request, parseKvp(raw), caseInsensitiveKvp(raw));
 
-        Map viewParams = request.getViewParams();
-        assertEquals(2, viewParams.size());
+        List<Map<String, String>> viewParamsList = request.getViewParams();
+        assertEquals(1, viewParamsList.size());
+        Map viewParams = viewParamsList.get(0);
         assertEquals("WHERE PERSONS > 1000000", viewParams.get("where"));
         assertEquals("ABCD", viewParams.get("str"));
     }
+    
+    public void testMultipleViewParams() throws Exception {
+        HashMap raw = new HashMap();
+        raw.put("layers", getLayerId(MockData.BASIC_POLYGONS) + "," + getLayerId(MockData.BASIC_POLYGONS));
+        raw.put("styles", "");
+        raw.put("format", "image/jpeg");
+        raw.put("srs", "epsg:3003");
+        raw.put("bbox", "-10,-10,10,10");
+        raw.put("height", "600");
+        raw.put("width", "800");
+        raw.put("request", "GetMap");
+        raw.put("service", "wms");
+        raw.put("viewParams", "where:WHERE PERSONS > 1000000;str:ABCD,where:WHERE PERSONS > 10;str:FOO");
+
+        GetMapRequest request = (GetMapRequest) reader.createRequest();
+        request = (GetMapRequest) reader.read(request, parseKvp(raw), caseInsensitiveKvp(raw));
+
+        List<Map<String, String>> viewParamsList = request.getViewParams();
+        assertEquals(2, viewParamsList.size());
+        Map viewParams = viewParamsList.get(0);
+        assertEquals("WHERE PERSONS > 1000000", viewParams.get("where"));
+        assertEquals("ABCD", viewParams.get("str"));
+        viewParams = viewParamsList.get(1);
+        assertEquals("WHERE PERSONS > 10", viewParams.get("where"));
+        assertEquals("FOO", viewParams.get("str"));
+    }
+    
+    public void testFanOutViewParams() throws Exception {
+        HashMap raw = new HashMap();
+        raw.put("layers", getLayerId(MockData.BASIC_POLYGONS) + "," + getLayerId(MockData.BASIC_POLYGONS));
+        raw.put("styles", "");
+        raw.put("format", "image/jpeg");
+        raw.put("srs", "epsg:3003");
+        raw.put("bbox", "-10,-10,10,10");
+        raw.put("height", "600");
+        raw.put("width", "800");
+        raw.put("request", "GetMap");
+        raw.put("service", "wms");
+        raw.put("viewParams", "where:WHERE PERSONS > 1000000;str:ABCD");
+
+        GetMapRequest request = (GetMapRequest) reader.createRequest();
+        request = (GetMapRequest) reader.read(request, parseKvp(raw), caseInsensitiveKvp(raw));
+
+        List<Map<String, String>> viewParamsList = request.getViewParams();
+        assertEquals(2, viewParamsList.size());
+        Map viewParams = viewParamsList.get(0);
+        assertEquals("WHERE PERSONS > 1000000", viewParams.get("where"));
+        assertEquals("ABCD", viewParams.get("str"));
+        viewParams = viewParamsList.get(1);
+        assertEquals("WHERE PERSONS > 1000000", viewParams.get("where"));
+        assertEquals("ABCD", viewParams.get("str"));
+    }
+    
 }
