My MVC 2 dropdown validation fire always even though i select a item from the list. I checked from firebug the dropdown is bind correcly with expected values.
Model:
public class Delivery
{
public int DeliveryID { get; set; }
[Required(ErrorMessage = "Please Select a Stock")]
public int? StockID { get; set; }
[Required(ErrorMessage = "Please Enter Expenses")]
public double OtherExpenses { get; set; }
public double Total { get; set; }
[Required(ErrorMessage = "Please Enter Description")]
public string Description { get; set; }
[Required(ErrorMessage = "Please Enter Arrived Date")]
public DateTime ArrivedDate { get; set; }
public string StockDescription { get; set; }
public IEnumerable<Stock> lstStock { get; set; }
}
Controller:
public ActionResult Create()
{
DeliveryRepository rep = new DeliveryRepository();
var model = new Delivery
{
lstStock = rep.GetStock()
};
return View(model);
}
//
// POST: /Delivery/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
Delivery del = new Delivery();
DeliveryRepository rep = new DeliveryRepository();
TryUpdateModel(del);
if (ModelState.IsValid)
{// TODO: Add insert logic here
del.ArrivedDate = Convert.ToDateTime(Request.Form["ArrivedDate"]);
del.Description = Request.Form["Description"];
del.OtherExpenses = Convert.ToDouble(Request.Form["OtherExpenses"]);
del.StockID = Convert.ToInt32(Request.Form["StockID"]);
del.Total = Convert.ToDouble(Request.Form["lblTotal"]) + del.OtherExpenses;
rep.Create(del);
rep.Save();
return RedirectToAction("Index");
}
else
{
var model = new Delivery
{
lstStock = rep.GetStock()
};
return View(model);
}
}
catch
{
return View();
}
}
View:
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.Label("Select Stock") %>
</div>
<div class="editor-field">
<%: Html.DropDownListFor(x => x.lstStock, new SelectList(Model.lstStock, "StockID", "Description"), "-- Please Select a Stock --")%>
<%: Html.ValidationMessageFor(model => model.StockID)%>
</div>
<div id="clslbl">
<br />
<label id="lblTotal"></label>
</div>
<br />
<div class="editor-label">
<%: Html.LabelFor(model => model.OtherExpenses) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.OtherExpenses) %>
<%: Html.ValidationMessageFor(model => model.OtherExpenses) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Description) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Description) %>
<%: Html.ValidationMessageFor(model => model.Description) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.ArrivedDate) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.ArrivedDate) %>
<%: Html.ValidationMessageFor(model => model.ArrivedDate) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
Issue was with my view
<div class="editor-field">
<%: Html.DropDownListFor(x => x.lstStock, new SelectList(Model.lstStock, "StockID", "Description"), "-- Please Select a Stock --")%>
<%: Html.ValidationMessageFor(model => model.StockID)%>
</div>
Should be changed as
<div class="editor-field">
<%: Html.DropDownListFor(x => x.StockID, new SelectList(Model.lstStock, "StockID", "Description"), "-- Please Select a Stock --")%>
<%: Html.ValidationMessageFor(model => model.StockID)%>
</div>
Related
I adding an admin area to an Asp.net MVC4 Application and I would consider myself a entry-level developer. My edit [HttpGet] action is working fine as it returns the values of asset. I have poured through a bunch of MVC4 specials online and most of them use the following for [HttpPost] Edit method:
[HttpPost]
public ActionResult Edit(ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel models)
{
try
{
if (ModelState.IsValid)
{
_entities.Entry(models).State = EntityState.Modified;
_entities.SaveChanges();
return RedirectToAction("Index", new { ID = models.ID });
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable able to save changes....epic fail!!!");
}
return View(models);
}
The problem is that I do not have access to use .Entry in the following:
_entities.Entry(models).State = EntityState.Modified;
I am obviously missing a reference that will enable me to use it, but I am not sure what it is.
Here is my ViewModel(I would have used DbContext, but they did not):
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using ITTESI.AssetTracker.Web.UI.Content.Classes;
namespace ITTESI.AssetTracker.Web.UI.ViewModels
{
public class AssetDetailsViewModel
{
public int ID { get; set; }
public string AssetIdentifier { get; set; }
public string ManufacturerName { get; set; }
public string Model { get; set; }
public string SchoolLocation { get; set; }
public string Status { get; set; }
public string Condition { get; set; }
// [DataType(DataType.MultilineText)]
public string Notes { get; set; }
public Utils.AssignReturn AssignReturnEligible { get; set; }
public string SchoolLocationCd { get; set; }
public string SchoolLocationDisplayValue { get; set; }
public AssignedUserViewModel AssignedUserViewModelObj { get; set; }
}
}
Here is my Admin Controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Metadata.Edm;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using ITTESI.AssetTracker.Data.EntityModel.Entity;
using ITTESI.AssetTracker.Data.EntityModel.Definition;
using System.Data.Entity;
using ITTESI.AssetTracker.Web.UI;
using ITTESI.AssetTracker.Web.UI.Content;
using ITTESI.AssetTracker.Web.UI.Content.Classes;
using ITTESI.AssetTracker.Web.UI.ViewModelBuilders;
using ITTESI.AssetTracker.Web.UI.ViewModels;
namespace ITTESI.AssetTracker.Web.UI.Controllers
{
public class AdminController : Controller
{
ExtendedITTESI_AssetTrackerEntities _entities = new ExtendedITTESI_AssetTrackerEntities();
public ActionResult Index(ViewModels.AssetDetailsViewModel assetDetails)
{
ViewBag.PageTitle = "Admin Search";
ViewBag.HideShowLocation = "hide";
ViewBag.SubmitButtonValue = "Search";
return View("Index", assetDetails);
}
[HttpGet]
public ActionResult Edit(ITTESI_AssetTracker_Asset asset) // 'ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel'
{
ViewBag.PageTitle = "Edit Asset";
ViewBag.SubmitButtonValue = "Save";
ViewBag.ShowLocation = true;
var model = _entities.ITTESI_AssetTracker_Asset.FirstOrDefault();
return View(model);
}
[HttpPost]
//public ActionResult Edit(ExtendedITTESI_AssetTrackerEntities ate)
public ActionResult Edit(ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel models)
{
try
{
if (ModelState.IsValid)
{
_entities.Entry(models).State = EntityState.Modified;
_entities.SaveChanges();
return RedirectToAction("Index", new { ID = models.ID });
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable able to save changes....epic fail!!!");
}
return View(models);
}
}
}
Here is my Edit View:
#model ITTESI.AssetTracker.Data.EntityModel.Entity.ITTESI_AssetTracker_Asset
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>ITTESI_AssetTracker_Asset</legend>
#Html.HiddenFor(model => model.ID)
<div class="editor-label">
#Html.LabelFor(model => model.AssetIdentifier)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetIdentifier)
#Html.ValidationMessageFor(model => model.AssetIdentifier)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssetConditionID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetConditionID)
#Html.ValidationMessageFor(model => model.AssetConditionID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.SchoolID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.SchoolID)
#Html.ValidationMessageFor(model => model.SchoolID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssetCategoryID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetCategoryID)
#Html.ValidationMessageFor(model => model.AssetCategoryID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.VendorID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.VendorID)
#Html.ValidationMessageFor(model => model.VendorID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssignedPersonID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssignedPersonID)
#Html.ValidationMessageFor(model => model.AssignedPersonID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssetStatusID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AssetStatusID)
#Html.ValidationMessageFor(model => model.AssetStatusID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ManufacturerID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ManufacturerID)
#Html.ValidationMessageFor(model => model.ManufacturerID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModelDetail)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ModelDetail)
#Html.ValidationMessageFor(model => model.ModelDetail)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CreatedOn)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CreatedOn)
#Html.ValidationMessageFor(model => model.CreatedOn)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CreatedByIdentifier)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CreatedByIdentifier)
#Html.ValidationMessageFor(model => model.CreatedByIdentifier)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModifiedOn)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ModifiedOn)
#Html.ValidationMessageFor(model => model.ModifiedOn)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModifiedByIdentifier)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ModifiedByIdentifier)
#Html.ValidationMessageFor(model => model.ModifiedByIdentifier)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Notes)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Notes)
#Html.ValidationMessageFor(model => model.Notes)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I also certain the problem is that DbContext for ExtendedITTESI_AssetTrackerEntities does not exist and after research a bit more that is part of the System.Data.Entity. The only code I have for ExtendedITTESI_AssetTrackerEntities is:
using System;
using Common.Logging;
using EFCachingProvider;
using EFCachingProvider.Caching;
using EFProviderWrapperToolkit;
using EFTracingProvider;
using ITTESI.AssetTracker.Data.EntityModel.Entity;
namespace ITTESI.AssetTracker.Data.EntityModel.Definition
{
public class ExtendedITTESI_AssetTrackerEntities : ITTESI_AssetTrackerEntities
{
private ILog logOutput;
public ExtendedITTESI_AssetTrackerEntities()
: this("name=ITTESI_AssetTrackerEntities")
{
}
public ExtendedITTESI_AssetTrackerEntities(string connectionString)
: base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
connectionString,
"EFTracingProvider",
"EFCachingProvider"
))
{
CachingPolicy = AssetTrackerEntitiesCachingPolicy.CachingPolicy();
Cache = AssetTrackerEntitiesCache.Cache();
}
#region Tracing Extensions
private EFTracingConnection TracingConnection
{
get { return this.UnwrapConnection<EFTracingConnection>(); }
}
public event EventHandler<CommandExecutionEventArgs> CommandExecuting
{
add { this.TracingConnection.CommandExecuting += value; }
remove { this.TracingConnection.CommandExecuting -= value; }
}
public event EventHandler<CommandExecutionEventArgs> CommandFinished
{
add { this.TracingConnection.CommandFinished += value; }
remove { this.TracingConnection.CommandFinished -= value; }
}
public event EventHandler<CommandExecutionEventArgs> CommandFailed
{
add { this.TracingConnection.CommandFailed += value; }
remove { this.TracingConnection.CommandFailed -= value; }
}
private void AppendToLog(object sender, CommandExecutionEventArgs e)
{
if (this.logOutput != null)
{
this.logOutput.Debug(e.ToTraceString().TrimEnd());
}
}
public ILog Log
{
get { return this.logOutput; }
set
{
if ((this.logOutput != null) != (value != null))
{
if (value == null)
{
CommandExecuting -= AppendToLog;
}
else
{
CommandExecuting += AppendToLog;
}
}
this.logOutput = value;
}
}
#endregion
#region Caching Extensions
private EFCachingConnection CachingConnection
{
get { return this.UnwrapConnection<EFCachingConnection>(); }
}
public ICache Cache
{
get { return CachingConnection.Cache; }
set { CachingConnection.Cache = value; }
}
public CachingPolicy CachingPolicy
{
get { return CachingConnection.CachingPolicy; }
set { CachingConnection.CachingPolicy = value; }
}
#endregion
}
}
I might have to create a model with DbContext is that fair to say?
Can I use anything besides .Entry? I appreciate the help, but with the way the app is set up I am not sure how to properly save edits back to the database.
there is a way besides .Entry for the Edit Action. EF is very clever, you can just fetch the object by ID form the database and change all the properties manually.
Ex:
[HttpPost]
public ActionResult Edit(ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel models)
{
try
{
if (ModelState.IsValid)
{
ITTESI.AssetTracker.Web.UI.ViewModels.AssetDetailsViewModel temp = _entities.dbname.firstOrDefault(x = > x.ID == models.ID);
temp.AssetIdentifier = models.AssetIdentifier ;
temp.ManufacturerName = models.ManufacturerName ;
.
.
.
_entities.SaveChanges();
return RedirectToAction("Index", new { ID = models.ID });
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable able to save changes....epic fail!!!");
}
return View(models);
}
EF will understand what entity you want to modify, and will update it with "_entities.saveChanges();"
I don't really know that this will work for you, but I think it's worth trying
I have a model class named Server and I have created a new ServerToEdit viewModel class, but when I am trying to submit the viewModel I will get the following error on the repository.save() method.
The model item passed into the dictionary is of type
'TMS.Models.Server', but this dictionary requires a model item of type
'TMS.ViewModels.ServerToEdit'.
The viewModel class is :-
public class ServerToEdit
{
public Server Server { get; set; }
[Required]
public String IPAddress { get; set; }
}
Part of the Create view is:-
model TMS.ViewModels.ServerToEdit
#* This partial view defines form fields that will appear when creating and editing entities *#
#Html.AntiForgeryToken()
<div class="editor-label">
#Html.LabelFor(model => model.Server.CustomerName)
</div>
<div class="editor-field">
#Html.EditorFor(model =>model.Server.CustomerName)
#Html.ValidationMessageFor(model =>model.Server.CustomerName)
</div>
<div class="editor-label">
IP Address
</div>
<div class="editor-field">
#Html.EditorFor(model => model.IPAddress)
#Html.ValidationMessageFor(model => model.IPAddress)
</div>
IPAddress
<div class="editor-label">
#Html.LabelFor(model =>model.Server.ILOIP)
</div>
<div class="editor-field">
#Html.EditorFor(model =>model.Server.ILOIP)
#Html.ValidationMessageFor(model =>model.Server.ILOIP)
</div>
The Create actin method is :-
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Server server, TechnologyIP technologyIP)
{
try
{
if (ModelState.IsValid)
{
repository.InsertOrUpdateServer(server,technologyIP);
repository.Save();
return RedirectToAction("Index");
}
Finally the InsertOrUpdateServer repository method is:-
public void InsertOrUpdateServer(Server server, TechnologyIP technologyIP)
{
if (server.ServerID == default(int))
{
// New entity
int technologyypeID = GetTechnologyTypeID("Server");
Technology technology = new Technology
{
IsDeleted = true,
TypeID = technologyypeID,
Tag = "S" + GetTagMaximumeNumber(technologyypeID).ToString()
};
InsertOrUpdateTechnology(technology);
Save();
var auditinfo = IntiateAudit(tms.AuditActions.SingleOrDefault(a => a.Name.ToUpper() == "ADD").ActionID,
tms.TechnologyTypes.SingleOrDefault(a => a.Name.ToUpper() == "Server").AssetTypeID,
"TDMGROUP\administrator", technology.TechnologyID);
server.ServerID = technology.TechnologyID;
technologyIP.TechnologyID = technology.TechnologyID;
tms.Servers.Add(server);
InsertOrUpdateTechnologyIP(technologyIP);
technology.IsDeleted = false;
InsertOrUpdateTechnology(technology);
InsertOrUpdateAudit(auditinfo);
}
else
{
// Existing entity
var auditinfo = IntiateAudit(tms.AuditActions.SingleOrDefault(a => a.Name.ToUpper() == "EDIT").ActionID,
tms.TechnologyTypes.SingleOrDefault(a => a.Name.ToUpper() == "Server").AssetTypeID,
"TDMGROUP\administrator", server.ServerID);
tms.Entry(server).State = EntityState.Modified;
tms.Entry(technologyIP).State = EntityState.Modified;
InsertOrUpdateAudit(auditinfo);
}
}
thanks in advance for any help ?
First of all, change your ViewModel to this:
public class ServerToEdit
{
public Server Server { get; set; }
public TechnologyIP TechnologyIP { get; set; }
}
And, change your Action to this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ServerToEdit serverToEdit)
{
if (ModelState.IsValid)
{
try
{
repository.InsertOrUpdateServer(serverToEdit.Server, serverToEdit.TechnologyIP);
repository.Save();
return RedirectToAction("Index");
}
catch
{
// Some code...
}
}
}
Then, in your View, you'll have:
#model TMS.ViewModels.ServerToEdit
#* This partial view defines form fields that will appear when creating and editing entities *#
#Html.AntiForgeryToken()
<div class="editor-label">
#Html.LabelFor(model => model.Server.CustomerName)
</div>
<div class="editor-field">
#Html.EditorFor(model =>model.Server.CustomerName)
#Html.ValidationMessageFor(model =>model.Server.CustomerName)
</div>
#Html.HiddenFor(model => model.TechnologyIP.TechnologyID)
<div class="editor-label">
IP Address
</div>
<div class="editor-field">
#Html.EditorFor(model => model.TechnologyIP.IPAddress)
#Html.ValidationMessageFor(model => model.TechnologyIP.IPAddress)
</div>
<div class="editor-label">
#Html.LabelFor(model =>model.Server.ILOIP)
</div>
<div class="editor-field">
#Html.EditorFor(model =>model.Server.ILOIP)
#Html.ValidationMessageFor(model =>model.Server.ILOIP)
</div>
I have this model:
public class Package
{
public string CustomerName { get; set; }
public List<Product> Products { get; set; }
public int Id { get; set; }
}
public class Product
{
public int Quantity { get; set; }
public string Name { get; set; }
public int Id { get; set; }
}
I have a Create's view for creating a new Package and one or many Create product's PartialView.
How I can submit the Product informations to the Product's controller without leave the View?
Here is my Product's Partialview code:
<% using (Ajax.BeginForm("Create", "Product", new AjaxOptions())) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Name) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Name) %>
<%: Html.ValidationMessageFor(model => model.Name) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Quantity) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Quantity) %>
<%: Html.ValidationMessageFor(model => model.Quantity) %>
</div>
<%-- <p>
<input type="submit" value="Create" />
</p>--%>
</fieldset>
<% } %>
Thank you
You can use AJAX to solve your problem. The code pode below post 3 values to YourController in YourAction.
jQuery('#YourButton').click(function (event) {
var jqxhr = $.post("YourController/YourAction", {
lastName: $("#tbLastName").val(),
firstName: $("#tbFirstName").val(),
id: $("#id").val()
},
function (data) {
$('#WhereResultAppear').html(data); //can be deleted
})
.success(function () {
$('#InCaseOfSuccess').html(data); //can be deleted
})
.error(function (jqXHR, status, error) {
$('#InCaseOfError').html(data); //can be deleted
})
.complete(function () {
$('#WhenActionIsComplete').html(data); //can be deleted
});
});
Give an id to your form in the partial view. and then use JQuery to send data by serializing the form.
$.post("controller/action", $("#formId").serialize(),
function(data) {
alert("Data Loaded: " + data);
});
And in the controller
Package pakage = new Package();
UpdateModel(pakage );
Although you can write code to serialize the data as the other answers mention, I would consider surrounding the fields in an
#using (Ajax.BeginForm("ActionOnController", new AjaxOptions{}))
{
}
This will do it all for you (as long as you include the necessary javascript e.g. jquery.unobtrusive-ajax.min.js)
Take a look at the AjaxOptions documentation. This allows you to (amongst other things) update another section after posting the values back. You can use this to indicate success
Martin
I have this Model:
public class Package
{
public string CustomerName { get; set; }
public List<Product> Products { get; set; }
}
public class Product
{
public int Quantity { get; set; }
public string Name { get; set; }
}
When I add the Create's view, the code is:
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.CustomerName) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.CustomerName) %>
<%: Html.ValidationMessageFor(model => model.CustomerName) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
How manage the Products list?
Can I get a button or something to create a new product and add it to the Products list?
Thank you
for creating buttn you can also do this use HTML.ActionLink() or Ajax.ActionLink() defined as a button like:
<% Response.Write(Html.ActionLink("Add Product", "Create", new { id = tId, tNum = tNum }, new { #class = "oldVal" })); %>
it'll create a button on your page, and here you can see different attributes (so just check them out you'll find it useful) ... and from both of this which to use is more depends upon your desired action ...
and in your controller:
public ActionResult Create()
{
// do same as mentioned by [gnome][1]
}
here is the example: modal popup, declared as a partial view of page
[partial view using Ajax.ActionLink()]
using (Ajax.BeginForm("Login", "Users", null, new AjaxOptions() { UpdateTargetId = "divLoginPopupContent" }))
{
Response.Write(Html.ValidationSummary(true));
%>
<ul class="chooseQuestion">
<li>
<div class="short">
<%= Html.LabelFor(model => model.LoginEmail)%>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model.LoginEmail)%>
<%= Html.ValidationMessageFor(model => model.LoginEmail)%>
</div>
</li><li>
<div class="short">
<%= Html.LabelFor(model => model.LoginPassword)%>
</div>
<div class="editor-field">
<%= Html.PasswordFor(model => model.LoginPassword)%>
<%= Html.ValidationMessageFor(model => model.LoginPassword)%>
</div>
</li><li>
<div class="checkbox">
<%= Html.CheckBoxFor(model => model.Remember)%>
<%= Html.LabelFor(model => model.Remember)%>
</div>
</li><li>
<input type="submit" class="button" value="Login" id="btnLoginSubmit" />
<div id="divlogin_ajaxloading" style="display:none; vertical-align:top; text-align:center;"><img alt="" src="/images/ajax-loader.gif" /></div>
</li>
</ul>
}
your partial view action:
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.LoginEmail, model.LoginPassword))
{
return Redirect("/MyPage");
}
else
{
ModelState.Clear();
return PartialView("LoginPopup", new LoginModel());
}
}
}
Just typed this up, haven't tested it but the basic idea is to list your products on the customer view with a button to add a new product for a customer.
To list Products for Customer:
<table>
<% foreach(var p in Customer.Products) { %>
<tr>
<td><%: p.Quantity %></td>
<td><%: p.Name %></td>
</tr>
<% } %>
</table>
<p><%: Html.ActionLink("Add Product", "Create", new { controller = 'Products' }, new { id = 'addProduct'}) %>
<div id="dialog"></div>
To add a new Product for a customer you could use jQuery UI to show a dialog; just pass the Customer Id
// assuming you've included jquery-ui
<script type="text/javascript">
$(document).ready(function() {
$('#dialog').dialog({
autoOpen : false,
button : {
'Save' : function() {
$.ajax({
url : $('#addProduct').attr('href'),
type : 'get'
success : function() {
alert('Product added!');
}
});
},
'Cancel' : function() {
$('#dialog').dialog('close');
}
}
});
$('#addProduct').click(function() {
var customerId = $('#CustomerId').val();
$('#dialog').dialog('open');
$('#Customer_Product_Id').val(customerId); // assuming there's a hidden field on the form
});
});
</script>
In your product controller return a partial
public ActionResult Create()
{
List<Product> products = new List<Product>() {
new Product() { Id = 1, Name = "Rice" },
new Product() { Id = 2, Name = 'Corn' }};
ViewData.Add("Products", new SelectList(products, "Id", "Name", ""));
Product product = new Product();
if (Request.IsAjaxRequest())
{
return PartailView("_CreateOrEdit", product)
}
return View("Create", product);
}
_Create view
<%: Html.TextBoxFor(model => model.Quantity) %>
<%: Html.DropDownList("Products") %>
<%: Html.HiddenFieldFor(model => model.Product.Customer.Id) %>
Why is my controller receiving an empty model in this case?
Using
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<X.Models.ProductModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h2>Product</h2>
<% using (Html.BeginForm() {%>
<%: Html.ValidationSummary(true) %>
<div class="editor-label">
Product Name
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Name) %>
<%: Html.ValidationMessageFor(model => model.Name) %>
</div>
<br />
<div class="editor-label">
Short Description
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.ShortDesc) %>
<%: Html.ValidationMessageFor(model => model.ShortDesc) %>
</div>
<br />
<div class="editor-label">
Long Description
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.LongDesc) %>
<%: Html.ValidationMessageFor(model => model.LongDesc) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
<% } %>
</asp:Content>
and the following controller.
using System.Web.Mvc;
using X.Lib.Services;
using X.Models;
namespace X.Admin.Controllers
{
public class ProductController : Controller
{
[HttpGet]
public ActionResult ProductData()
{
return View();
}
[HttpPost]
public ActionResult ProductData(ProductModel NewProduct)
{
//Validate and save
if(ModelState.IsValid)
{
//Save And do stuff.
var ProductServ = new ProductService();
ProductServ.AddProduct(NewProduct);
}
return View();
}
}
}
Model:
public class ProductModel
{
public int ID;
[Required(ErrorMessage = "Name is required")]
public string Name;
public string LongDesc;
public string ShortDesc;
}
EDIT: you need to use properties not variables
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
public string LongDesc { get; set; }
public string ShortDesc { get; set; }
Also...
You are not passing the model back to the view.
return View(NewProduct);
I normally pass a blank model in to the GET action too
ProductModel NewProduct = new ProductModel();
return View(NewProduct);
This way if you wish to set any default values you can do so easily.
Code example in full I've also added try and catch blocks around the adding of the product and given example views you could be returning on success or fail:
[HttpGet]
public ActionResult ProductData()
{
ProductModel NewProduct = new ProductModel();
return View(NewProduct);
}
[HttpPost]
public ActionResult ProductData(ProductModel NewProduct)
{
//Validate and save
if(!ModelState.IsValid)
{
// Return the model back to view
return View(NewProduct);
}
try{
//Save And do stuff.
var ProductServ = new ProductService();
ProductServ.AddProduct(NewProduct);
}
catch(Exception){
return View("Fail");
}
return View("Success");
}