I'm sorry if this ends up simple or stupid question, I'm very new to MVC and Razor, being dropped in deep end with no formal training on anything current...
I don't understand why the data in my model is available in my first view is not available in my second view.
Controller initiates an instance of model using code
Product _Product = new Product();
then the first view is called after a bunch of initial data queries have ran. The view is called using
return View("Attributes", _Product)
to call the view passing it the _Product instance of model.
My first view does many things but relevant to this question it shows a table using foreach row on dataset filled by SQL on controller stored on model.
@foreach(DataRow row in Model.attList.Tables[0].Rows)
The view has multiple buttons, such as add, delete, edit... Each have their own action assigned such as
<input type="submit" class="btn btn-primary" name="action:btnDelete" value="Delete" />
If the user presses one of the buttons on that view that triggers HTTPPOST. One of them calls a new view but if I pass my model to that view again, the data is now blank? I am passing the model to the view, and accepting it in HTTPPOST and passing it to the next view (or so I thought).
I'm using very generic beginning to form
@using (Html.BeginForm()) {
The code in controller for this button is very basic
[HttpPost]
[MultipleButton(Name = "action", Argument = "btnEditValues")]
public ActionResult btnEditValues(Product _Product)
{
return View("btnEditValues", _Product);
}
But then in that 2nd view if I try to re-display the same table, it now says my Model.attList is empty. I added quick script of console.log(@Model.attList);
and when I click the button it is showing the 2nd view but the console is logging a blank value (not NULL, just blank)...
I'm sure I'm just missing something simple - or perhaps I'm trying to do something I can't ???
The following was copied/pasted, without edit, into this question from an errantly posted "answer" which was intended to be an edit on the question. The answer has been flagged and should be removed.
Per David's Request.
Here is complete M, V, V, and C (didn't include other 2 views they don't use Model and both work)...
!!! NOTE !!!: This code is being used somewhere everyone has SQL manager and Admin rights to SQL server. As such SQL parameters were not used. This code would be vulnerable to SQL injection if used on open Website.
Model
namespace P21.Rules.Visual.Areas.KCDA_ItemMaint_Attributes.Models
{
public class Product
{
// Variables used between views
public int RowSelected { get; set; }
// Declare datasets to use as list
public DataSet attList { get; set; }
public DataSet lowList { get; set; }
}
}
Controller
namespace P21.Rules.Visual.Areas.KCDA_ItemMaint_Attributes.Controllers
{
#region Multiple Buttons
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultipleButtonAttribute : ActionNameSelectorAttribute
{
public string Name { get; set; }
public string Argument { get; set; }
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
{
var isValidName = false;
var keyValue = string.Format("{0}:{1}", Name, Argument);
var value = controllerContext.Controller.ValueProvider.GetValue(keyValue);
if (value != null)
{
controllerContext.Controller.ControllerContext.RouteData.Values[Name] = Argument;
isValidName = true;
}
return isValidName;
}
}
#endregion
public class KCDA_ItemMaint_AttributesController : BaseRuleController
{
#region public variables
// public dataset for loading SQL values
DataSet attload = new DataSet();
DataSet lowload = new DataSet();
#endregion
#region Main Action
// GET: KCDA_ItemMaint_Attributes/KCDA_ItemMaint_Attributes
public ActionResult Attributes()
{
if (Data.Fields["item_id"].FieldValue == string.Empty)
{
// Report error and prevent form pop-up if no product group has been selected
Rule.RuleResult.Success = false;
Rule.RuleResult.Message = "You must first select an Item before listing Attributes";
return RedirectToAction("Close", "Initialize", new { area = "" });
}
else
{
try
{
// Create container and setup Group values
Product _Product = new Product();
//Get Attributes for selected item
LoadAttributes();
_Product.attList = attload.Copy();
//Get ECom Server Side Attribute for selected item
LoadLower();
_Product.lowList = lowload.Copy();
return View("Attributes", _Product);
}
catch (Exception ex)
{
//catch the error and send it to the Error view with the HandleErrorInfo
return View("Error", new HandleErrorInfo(ex, "KCDA_ItemMaint_Attributes", "Attributes"));
}
}
}
#endregion
#region Buttons
[HttpPost]
[MultipleButton(Name = "action", Argument = "btnDelete")]
public ActionResult btnDelete(Product _Product)
{
// create SQL command to delete the
string sqlDelete = "UPDATE BL_ProductAttribute SET DeleteFlag = '1' WHERE [KEY] = '" + _Product.RowSelected + "'";
// Run the sqlDELETE command
SqlCommand cmdDelete = new SqlCommand(sqlDelete, P21SqlConnection);
cmdDelete.ExecuteNonQuery();
SqlDataAdapter daDelete = new SqlDataAdapter(cmdDelete);
return View("btnDelete", _Product);
}
[HttpPost]
[MultipleButton(Name = "action", Argument = "btnAdd")]
public ActionResult btnAdd(Product _Product)
{
// Retrieve selected/loaded drop-down values
string ddGroup = Request["ApplyGroup"];
string ddName = Request["AttributeName"];
string ddValue = Request["AttributeValue"];
if (ddValue == "")
{
ViewBag.msg = "No Value Selected";
}
else
{
// default duplicate count to 0
int duplicate = 0;
// create SQL command to check for duplicate attribute
string sqlDuplicate = "SELECT COUNT(1) FROM BL_ProductAttribute " +
"WHERE SKU = '" + Data.Fields["item_id"].FieldValue + "' " +
"AND AttributeGroupName = '" + ddGroup + "'";
// Run the sqlDuplicate command
SqlCommand cmdDuplicate = new SqlCommand(sqlDuplicate, P21SqlConnection);
cmdDuplicate.CommandType = CommandType.Text;
SqlDataAdapter daDuplicate = new SqlDataAdapter(cmdDuplicate);
// Create dataset from duplicate check
DataTable dupcheck = new DataTable();
daDuplicate.Fill(dupcheck);
// Set count if exists
duplicate = int.Parse(dupcheck.Rows[0][0].ToString());
// if exists update/undelete otherwise insert
if (duplicate > 0)
{
// create SQL command to update the attribute
string sqlAdd = "UPDATE BL_ProductAttribute " +
"SET BL_ProductAttribute.Value = '" + ddValue.Replace("'", "''") + "', " +
"BL_ProductAttribute.AttributeTitle = '" + ddName + "', " +
"BL_ProductAttribute.DeleteFlag = 0, " +
"BL_ProductAttribute.ProductID = '" + Data.Fields["product_group_id"].FieldValue + "' " +
"FROM BL_ProductAttribute " +
"WHERE SKU = '" + Data.Fields["item_id"].FieldValue + "' AND AttributeGroupName = '" + ddGroup + "' ";
// Run the sqlAdd command
SqlCommand cmdAdd = new SqlCommand(sqlAdd, P21SqlConnection);
cmdAdd.ExecuteNonQuery();
SqlDataAdapter daAdd = new SqlDataAdapter(cmdAdd);
ViewBag.msg = "Record Updated";
}
else
{
// If adding determine next key value for unique ID
string newKey = string.Empty;
// create SQL command to get next KEY value for insert reset current maxkey
string sqlMax2 = "SELECT max([key])+1 FROM BL_AttributeEnumValue";
// Run the sqlMax command
SqlCommand cmdKey2 = new SqlCommand(sqlMax2, P21SqlConnection);
cmdKey2.CommandType = CommandType.Text;
SqlDataAdapter daKey2 = new SqlDataAdapter(cmdKey2);
// Create dataset from newKey check and assign to newKey
DataTable KeyCheck2 = new DataTable();
daKey2.Fill(KeyCheck2);
newKey = KeyCheck2.Rows[0][0].ToString();
// create SQL command to update the attribute
string sqlAdd = "INSERT INTO BL_ProductAttribute ([Key], ProductId, SKU, AttributeTitle, " +
"isSKUlevel, isRequired, isDefault, Value, AttributeGroupName, DeleteFlag) " +
"VALUES('" + newKey + "', '" + Data.Fields["product_group_id"].FieldValue + "', '" +
Data.Fields["item_id"].FieldValue + "', '" + ddName + "', 1, 1, 1, '" +
ddValue.Replace("'", "''") + "', '" + ddGroup + "', 0)";
// Run the sqlAdd command
SqlCommand cmdAdd = new SqlCommand(sqlAdd, P21SqlConnection);
cmdAdd.ExecuteNonQuery();
SqlDataAdapter daAdd = new SqlDataAdapter(cmdAdd);
ViewBag.msg = "Record Added";
}
}
return View("btnAdd", _Product);
}
[HttpPost]
[MultipleButton(Name = "action", Argument = "btnEditValues")]
public ActionResult btnEditValues(Product _Product)
{
return View("btnEditValues", _Product);
}
#endregion
#region SQL Loads
private void LoadAttributes()
{
// Define SQL select command
string sqlAttributes = "SELECT * FROM BL_ProductAttribute " +
"WHERE SKU = '" + Data.Fields["item_id"].FieldValue + "' AND DeleteFlag = '0' " +
" AND AttributeGroupName in ('SKU_Color', 'SKU_SelectableAttribute_1', 'SKU_SelectableAttribute_2')";
// Set SQL command type to text and run it
SqlCommand cmdlist = new SqlCommand(sqlAttributes, P21SqlConnection);
cmdlist.CommandType = CommandType.Text;
SqlDataAdapter dalist = new SqlDataAdapter(cmdlist);
// Load results from SQL into DataSet
dalist.Fill(attload);
}
private void LoadLower()
{
string DBconn = "vsldb1";
// Define SQL select command
string sqllist = "SELECT [Key], ProductID, SKU, AttributeTitle, isSKUlevel, isRequired, isDefault, " +
"\"Value\" = Case " +
"when (AttributeTitle = 'KCDASKUStatus' and ltrim(convert(varchar,Value)) = '0') then '0 - Warehouse Regular Item' " +
"when (AttributeTitle = 'KCDASKUStatus' and ltrim(convert(varchar,Value)) = '1') then '1 - Not on Website/Pending' " +
"when (AttributeTitle = 'KCDASKUStatus' and ltrim(convert(varchar,Value)) = '2') then '2 - RFQ' " +
"when (AttributeTitle = 'KCDASKUStatus' and ltrim(convert(varchar,Value)) = '3') then '3 - Limited Quote' " +
"when (AttributeTitle = 'KCDASKUStatus' and ltrim(convert(varchar,Value)) = '4') then '4 - Discontinued/Obsolete' " +
"when (AttributeTitle = 'KCDASKUStatus' and ltrim(convert(varchar,Value)) = '5') then '5 - Specials' " +
"when (AttributeTitle = 'KCDASKUStatus' and ltrim(convert(varchar,Value)) = '6') then '6 - Direct Ship' " +
"when (AttributeTitle = 'KCDASKUStatus' and ltrim(convert(varchar,Value)) = '7') then '7 - Offline' " +
"else value end, AttributeGroupName, UpdateFlag FROM OPENDATASOURCE('SQLOLEDB','Data Source=" + DBconn + ";user " +
"id=sa;password=KCDAAdmin').KCDA.dbo.KCDA_ProductAttribute PA" +
" WHERE PA.SKU = '" + Data.Fields["item_id"].FieldValue + "' AND PA.AttributeGroupName not in " +
"('SKU_Color', 'SKU_SelectableAttribute_1', 'SKU_SelectableAttribute_2')";
// Set SQL command type to text and run it
SqlCommand cmdlist = new SqlCommand(sqllist, P21SqlConnection);
cmdlist.CommandType = CommandType.Text;
SqlDataAdapter dalist = new SqlDataAdapter(cmdlist);
// Load results from SQL into DataSet
dalist.Fill(lowload);
}
#endregion
#region Drop Downs
[HttpPost]
public ActionResult GetAttributeNames(string selectedOption)
{
// Define variables for JSON query to use
JsonResult result = new JsonResult();
List<string> attNames = new List<string>();
List<string> attValues = new List<string>();
if (selectedOption != null)
{
// SQL to get attribute name for the selected attribute group for this product group
string sql = "SELECT Title FROM BL_Attribute (NOLOCK) WHERE BL_Attribute.DeleteFlag = '0' AND BL_Attribute.AttributeGroupName = '" + selectedOption + "'" +
" AND BL_Attribute.Title in (select AD.AttributeTitle from BL_AttributeDept AD where AD.product_group_id = '" + Data.Fields["product_group_id"].FieldValue.Substring(0, 2) +"')";
using (SqlCommand selectAttNames = new SqlCommand(sql, P21SqlConnection))
{
using (SqlDataReader reader = selectAttNames.ExecuteReader())
{
while (reader.Read())
{
attNames.Add(reader["Title"].ToString());
}
}
}
// SQL to get list of current available values for this attribute type
string sql2 = "SELECT Value FROM BL_AttributeEnumValue (NOLOCK) WHERE DeleteFlag = '0' and AttributeTitle = '" +
attNames[0] + "' ORDER BY Value";
using (SqlCommand selectAttValues = new SqlCommand(sql2, P21SqlConnection))
{
using (SqlDataReader reader2 = selectAttValues.ExecuteReader())
{
while (reader2.Read())
{
attValues.Add(reader2["Value"].ToString());
}
}
}
// define return object
var retObj = new
{
retNames = attNames,
retValues = attValues
};
return Json(retObj, JsonRequestBehavior.AllowGet);
}
return Json(new { Success = "false" });
}
#endregion
#region Edit Values
#endregion
#region Close Rule
[HttpPost]
public ActionResult Return()
{
Rule.RuleResult.Success = true;
//IMPORTANT - This is what returns the Visual Rule control back to the server
//DO NOT REMOVE
return RedirectToAction("Close", "Initialize", new { area = "" });
}
#endregion
}
}
Attributes View
@using P21.Rules.Visual.Areas.KCDA_ItemMaint_Attributes.Models
@using System.Data
@model Product
@{
ViewBag.Title = "Attributes";
Layout = "~/Views/Shared/_VisualRuleLayout.cshtml";
var listAttGroups = new List<SelectListItem>
{
new SelectListItem { Text = "SKU_Color", Value = "SKU_Color"},
new SelectListItem { Text = "SKU Select Att 1", Value = "SKU_SelectableAttribute_1"},
new SelectListItem { Text = "SKU Select Att 2", Value = "SKU_SelectableAttribute_2"}
};
}
@section scripts{
<script>
$(function () {
$("#ApplyGroup").change(function () {
var option = $(this).val();
//Clear and activate 2nd and 3rd drop down
$("#AttributeName").empty();
$("#AttributeValue").empty();
$("#AttributeName").prop('disabled', false);
$("#AttributeValue").prop('disabled', false);
var url = "GetAttributeNames?selectedOption=" + option;
$.post(url, function (retObj) {
$.each(retObj.retNames, function (i, attName) {
$("#AttributeName").append($('<option></option>').val(attName).html(attName));
});
$.each(retObj.retValues, function (i, attValue) {
$("#AttributeValue").append($('<option></option>').val(attValue).html(attValue));
});
});
});
});
</script>
}
@using (Html.BeginForm())
{
<div class="container">
<div class="row">
<label class="col-md-3 control-label" for="ApplyGroup" id="lblApplyGroup">Attribute Group</label>
<label class="col-md-3 control-label" for="AttributeName" id="lblAttributeName">Attribute Name</label>
<label class="col-md-2 control-label" for="AttributeValue" id="lblAttributeValue">Attribute Value</label>
<div class="col-md-2">
<input type="submit" class="btn btn-primary" name="action:btnEditValues" value="Edit Values" />
</div>
</div>
<div class="row" style="padding-top:5px">
<div class="col-md-3">
@Html.DropDownList("ApplyGroup", listAttGroups, "Select Group", new { @id = "ApplyGroup", @class = "form-control" })
</div>
<div class="col-md-3">
@Html.DropDownList("AttributeName", new List<SelectListItem>(), new { @id = "AttributeName", @class = "form-control", disabled = "disabled" })
</div>
<div class="col-md-3">
@Html.DropDownList("AttributeValue", new List<SelectListItem>(), new { @id = "AttributeValue", @class = "form-control", disabled = "disabled" })
</div>
<div class="col-md-3">
<span class="pull-right">
<input type="submit" class="btn btn-primary" name="action:btnAdd" value="Add\Update" />
</span>
</div>
</div>
<div class="row" style="padding-top:20px">
<div class="col-md-10">
</div>
<div class="col-md-2">
<span class="pull-right">
<input type="submit" class="btn btn-primary" name="action:btnDelete" value="Delete" />
</span>
</div>
</div>
<div class="row" style="padding-top:10px">
<div class="col-md-12">
<table id="attTable" style="width:100%" cellpadding="0" cellspacing="0" border="1" class="row">
<tbody>
<tr style="background-color: #F0F8FF;">
<th></th>
<th>Dept</th>
<th>Item #</th>
<th>Attribute Name</th>
<th>SKU Level</th>
<th>Required</th>
<th>Default</th>
<th>Attribute Value</th>
<th>Attribute Group</th>
</tr>
@foreach (DataRow row in Model.attList.Tables[0].Rows)
{
<tr class="selectable-row">
<td>@Html.RadioButtonFor(m => Model.RowSelected, row[0])</td>
<td>@row[1]</td>
<td>@row[2]</td>
<td>@row[3]</td>
<td>@row[4]</td>
<td>@row[5]</td>
<td>@row[6]</td>
<td>@row[7]</td>
<td>@row[8]</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="row" style="padding-top:50px">
<div class="col-md-12">
<table id="lowTable" style="width:100%" cellpadding="0" cellspacing="0" border="1" class="row">
<tbody>
<tr style="background-color: #F0F8FF;">
<th>Dept</th>
<th>Item #</th>
<th>Attribute Name</th>
<th>SKU Level</th>
<th>Required</th>
<th>Default</th>
<th>Attribute Value</th>
<th>Attribute Group</th>
</tr>
@foreach (DataRow row in Model.lowList.Tables[0].Rows)
{
<tr class="selectable-row">
<td>@row[1]</td>
<td>@row[2]</td>
<td>@row[3]</td>
<td>@row[4]</td>
<td>@row[5]</td>
<td>@row[6]</td>
<td>@row[7]</td>
<td>@row[8]</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
}
btnEditValues View
@using P21.Rules.Visual.Areas.KCDA_ItemMaint_Attributes.Models
@using System.Data
@model Product
@{
ViewBag.Title = "btnEditValues";
Layout = "~/Views/Shared/_VisualRuleLayout.cshtml";
var listAttGroups = new List<SelectListItem>
{
new SelectListItem { Text = "SKU_Color", Value = "SKU_Color"},
new SelectListItem { Text = "SKU Select Att 1", Value = "SKU_SelectableAttribute_1"},
new SelectListItem { Text = "SKU Select Att 2", Value = "SKU_SelectableAttribute_2"}
};
}
@section scripts{
<script>
console.log(@Model.attList);
</script>
}
<p align="right"><button type="button" class="btn btn-primary" onclick="location.href='@Url.Action("Attributes", "KCDA_ItemMaint_Attributes")'">X</button></p>
<center><h2>Edit Item Attribute Availble Values</h2></center>
@using (Html.BeginForm())
{
<div class="container">
<div class="row">
<label class="col-md-4 control-label" for="EditApplyGroup" id="lblEApplyGroup">Attribute Group</label>
<label class="col-md-4 control-label" for="EditAttributeName" id="lblEAttributeName">Attribute Name</label>
</div>
<div class="row" style="padding-top:5px">
<div class="col-md-4">
@Html.DropDownList("EditApplyGroup", listAttGroups, "Select Group", new { @id = "EditApplyGroup", @class = "form-control" })
</div>
<div class="col-md-4">
@Html.DropDownList("EditAttributeName", new List<SelectListItem>(), "Select Name", new { @id = "EditAttributeName", @class = "form-control", disabled = "disabled" })
</div>
</div>
<div class="row" style="padding-top:10px">
<div class="col-md-12">
<table id="attEditTable" style="width:100%" cellpadding="0" cellspacing="0" border="1" class="row">
<tbody>
<tr style="background-color: #F0F8FF;">
<th></th>
<th>Attribute Value</th>
<th>Item Count</th>
</tr>
</tbody>
</table>
</div>
</div>
</div>
}