How do you send data to controller with ajax.beginform? - ajax

This is my method on controller "sale"
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Models.account account)
{
Models.sale creaventa = new Models.sale();
//creaventa.account = cliente;
creaventa.createdon = DateTime.Now;
creaventa.idaccount = account.id;
creaventa.modifiedon = DateTime.Now;
creaventa.status = 0;
context.sales.Add(creaventa);
context.SaveChanges();
// return "venta creada";
return View();
}
and this is the partial view
#model List<modal3.Models.account>
#{
ViewBag.Title = "Create";
}
<select class="form-control" id="control1">
#{
foreach (var cliente in Model)
{
<option value="#cliente.id"> #cliente.name</option>
}
}
</select>
#*#using (Html.BeginForm("create", "sale", FormMethod.Post, new {id="my-form" }))
{
#Html.AntiForgeryToken()
<button type="submit" class="btn btn-default" value="Create" id="btncrear">
Iniciar Venta
</button>
}*#
#using (
Ajax.BeginForm("create","sale",new AjaxOptions()
{
HttpMethod ="Post",
InsertionMode = InsertionMode.Replace,
})
)
{
#Html.AntiForgeryToken()
<button type="submit" class="btn btn-default" value="Create" id="btncrear">
Iniciar Venta
</button>
}
This does enter to method with this does not send the model.
Then:
How to send a model?
How to send a lot of objects?
this is my model
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace modal3.Models
{
using System;
using System.Collections.Generic;
public partial class sale
{
public sale()
{
this.saledetails = new HashSet<saledetail>();
}
public int id { get; set; }
public Nullable<System.DateTime> createdon { get; set; }
public Nullable<System.DateTime> modifiedon { get; set; }
public Nullable<int> status { get; set; }
public Nullable<int> idaccount { get; set; }
public virtual account account { get; set; }
public virtual ICollection<saledetail> saledetails { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace modal3.Models
{
[MetadataType (typeof (sale_validation ))]
public partial class sale
{
}
public class sale_validation
{
//2015-06-17 22:07:26.353 2015-06-17 22:07:26.353 1 1
[Display (Name="")]
[HiddenInput (DisplayValue =false )]
public Nullable<System.DateTime> createdon { get; set; }
[Display(Name = "")]
[HiddenInput(DisplayValue = false)]
public Nullable<System.DateTime> modifiedon { get; set; }
[Display(Name = "")]
[HiddenInput(DisplayValue = false)]
public Nullable<int> status { get; set; }
public Nullable<int> idaccount { get; set; }
}
}

To make you understand how AJAX FORM works, I created below code -
Lets say our model -
public class Sale
{
public string SaleOwner { get; set; }
public virtual Account Account { get; set; }
}
public class Account
{
public string Name { get; set; }
}
I created two controller actions -
public ActionResult adatas()
{
return View();
}
[HttpPost]
public JsonResult Create(Sale s)
{
return Json("true");
}
The first controller action return following view -
#model WebApplication1.Controllers.Sale
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
#using (Ajax.BeginForm("Create", "Sale", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "done"
}))
{
#Html.TextBoxFor(m => m.SaleOwner)
#Html.TextBoxFor(m => m.Account.Name)
<input type="submit" value="click" />
}
<div id="done">
</div>
View Renders as follows -
Once we click on button, with breakpoints in the code -
Once AJAX POST happens, output would be -

Related

returning null value from populated selectlist with DB data

I'm implementing asp.net core MVC project. In my controller class called ApiApplicant, Create method, I have 3 selectlists that its items should be populated from a table called APIApplicantHistory. My models and create method and view are implemented like following:
using System.Collections.Generic;
namespace CSDDashboard.Models
{
public partial class Apiapplicant
{
public Apiapplicant()
{
ApiApplicantHistory = new HashSet<ApiApplicantHistory>();
}
public int Id { get; set; }
public string ApiRequestDate { get; set; }
public int? ApiRequestNo { get; set; }
public int? Apiid { get; set; }
public int? ApplicantId { get; set; }
public int? GateId { get; set; }
public string NocRequestDate { get; set; }
public string NocRequestNo { get; set; }
public string Url { get; set; }
public string Description { get; set; }
public bool? IsDeleted { get; set; }
public virtual Api Api { get; set; }
public virtual Applicant Applicant { get; set; }
public virtual Gate Gate { get; set; }
public virtual ICollection<ApiApplicantHistory> ApiApplicantHistory { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace CSDDashboard.Models
{
public partial class ApiApplicantHistory
{
public int Id { get; set; }
public int? ApiApplicantId { get; set; }
public string Date { get; set; }
public int? SentResponseType { get; set; }
public int? UnconfirmedReason { get; set; }
public int LastReqStatus { get; set; }
public string Description { get; set; }
public virtual Apiapplicant ApiApplicant { get; set; }
public virtual EntityType LastReqStatusNavigation { get; set; }
public virtual EntityType SentResponseTypeNavigation { get; set; }
public virtual EntityType UnconfirmedReasonNavigation { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace CSDDashboard.Models
{
public partial class EntityType
{
public EntityType()
{
ApiApplicantHistoryLastReqStatusNavigation = new HashSet<ApiApplicantHistory>();
ApiApplicantHistorySentResponseTypeNavigation = new HashSet<ApiApplicantHistory>();
ApiApplicantHistoryUnconfirmedReasonNavigation = new HashSet<ApiApplicantHistory>();
}
public int Id { get; set; }
public string Name { get; set; }
public string EntityKey { get; set; }
public virtual ICollection<ApiApplicantHistory> ApiApplicantHistoryLastReqStatusNavigation { get; set; }
public virtual ICollection<ApiApplicantHistory> ApiApplicantHistorySentResponseTypeNavigation { get; set; }
public virtual ICollection<ApiApplicantHistory> ApiApplicantHistoryUnconfirmedReasonNavigation { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CSDDashboard.Models
{
public class APIApplicantViewModel
{
public Apiapplicant apiApplicantvm { get; set; }
public ApiApplicantHistory apiApplicantHistoryvm { get; set; }
}
}
public class ApiapplicantsController : Controller
{
private readonly CSSDDashboardContext _context;
public ApiapplicantsController(CSSDDashboardContext context)
{
_context = context;
}
public IActionResult Create()
{
ViewData["sentResponseType"] = new SelectList(_context.EntityType.Where(g => g.EntityKey == "sentResponseType").ToList(), "ID", "name");
ViewData["unconfirmedReason"] = new SelectList(_context.EntityType.Where(g => g.EntityKey == "unconfirmedReason").ToList(), "ID", "name");
ViewData["lastReqStatus"] = new SelectList(_context.EntityType.Where(g => g.EntityKey == "lastRequestStatus").ToList(), "ID", "name");
return View();
}
}
And a part of create view implementation:
#model CSDDashboard.Models.APIApplicantViewModel
#{
ViewData["Title"] = "create";
}
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="apiApplicantvm.GateId" class="control-label"></label>
<select asp-for="apiApplicantvm.GateId" class="form-control" asp-items="ViewBag.GateId"></select>
</div>
<div class="form-group">
<label asp-for="apiApplicantHistoryvm.SentResponseType" class="control-label"></label>
<select asp-for="apiApplicantHistoryvm.SentResponseType" class="form-control" asp-items="ViewBag.sentResponseType"></select>
</div>
<div class="form-group">
<label asp-for="apiApplicantHistoryvm.UnconfirmedReason" class="control-label"></label>
<select asp-for="apiApplicantHistoryvm.UnconfirmedReason" class="form-control" asp-items="ViewBag.unconfirmedReason"></select>
</div>
<div class="form-group">
<label asp-for="apiApplicantHistoryvm.LastReqStatus" class="control-label"></label>
<select asp-for="apiApplicantHistoryvm.LastReqStatus" class="form-control" asp-items="ViewBag.lastReqStatus"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
In create method, all the viewData are filled with the correct related data but the problem is existing in Create view, after running the project an error like below is shown in Create page:
An unhandled exception occurred while processing the request.
NullReferenceException: Object reference not set to an instance of an object.
After debugging the code I understand that In create view, apiApplicantvm is not null but apiApplicantHistoryvm returns null and the above error is because of that. I appreciate if anyone could tells me how to fix the problem.
I hope you would be using EF core as ORM because you are using Asp.net core.
To load related data in EF core.
It can be done in 2 ways or Lazy loading
Eager loading
_context.EntityType.Where(g=>g.EntityKey=="sentResponseType")
.Include(x=>x.ApiApplicantHistoryLastReqStatusNavigation).ToList()
OR
Lazy loading
on your modal creating
protected override void
OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder .UseLazyLoadingProxies() .UseSqlServer(myConnectionString);
OR
on startup.cs of your core MVC project
Lazy loading example.
.AddDbContext<BloggingContext>(
b => b.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString));
for more info learn.microsoft.com/en-us/ef/core/querying/related-data
https://learn.microsoft.com/en-us/ef/core/querying/related-data
Thank you very much for the answers. I'm using EF core and I changed my code as what you suggested. I added ViewData["sentResponseType"] = new SelectList(_context.EntityType.Where(g => g.EntityKey == "sentResponseType")
.Include(x => x.ApiApplicantHistoryLastReqStatusNavigation).ToList(), "ID", "name");
in my create method.
And my problem is here in Create view, in the below line there exists a null value in apiApplicantHistoryvm:
Thank you for the help. The problem was here in my code
ViewData["sentResponseType"] = new SelectList(_context.EntityType.Where(g => g.EntityKey == "sentResponseType").ToList(), "ID", "name");
I should use Id instead of ID according to my EntityType model.

Razor - Passing DropDownList selected value to Controller via Ajax.BeginForm

I am trying to pass the dropdownlist value to my controller so I can add the values to a list of paycodes but I keep getting a "Value cannot be null." error. My paycode list has many items in it. Not sure what is null or wrong here...
INNER EXCEPTION
Value cannot be null.
Parameter name: source
VIEW
<!-- products input-->
<div class="control-group col-lg-6">
<label class="control-label">Product</label>
<div class="controls">
#using (Ajax.BeginForm("AddPayCode", "Referral",
new AjaxOptions()
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "PayCodes",
Url = Url.Action("AddPayCode", "Referral")
}))
{
#Html.ValidationSummary()
#Html.DropDownListFor(model => model.SelectedPayCode, new SelectList(Model.PayCodes.ToList(), "Id", "Description"), "- Select -")
<input type="submit" value="Add" />
}
</div>
</div>
CONTROLLER
[HttpPost]
public void AddPayCode(ReferralModel model)
{
var test = model.SelectedPayCode;
//TODO: Add to model.Referral.PayCodes list and return list of selected items
}
MODEL
public class ReferralModel
{
public Customer Customer { get; set; }
public Employee Employee { get; set; }
public List<PayCode> PayCodes { get; set; }
public int SelectedPayCode { get; set; }
public Referral Referral { get; set; }
}
DOMAIN OBJECT
public class Referral
{
[Key]
public int Id { get; set; }
public int CustomerId { get; set; }
public int EmployeeId { get; set; }
public decimal Total { get; set; }
public virtual List<PayCode> PayCodes { get; set; }
public virtual Customer Customer { get; set; }
public virtual Employee Employee { get; set; }
}
Objective :
User chooses a paycode from the dropdown and clicks "Add" Paycode is
added to the referral PayCodes list
Controller returns the list of paycodes selected to the view (not
yet implemented)
The issue was the controller is missing the property of the dropdown list.
[HttpPost]
public void AddPayCode(ReferralModel model, ** string SelectedPayCode ** <-- missing)
{
var test = SelectedPayCode;
//TODO: Add to model.Referral.PayCodes list and return list of selected items
}

No view updating after viewmodel been changed

can't find whats wrong and can't find answer anywhere. My problem is my view not updated after view model have bean changed
ViewModel:
public class OrderView
{
public Customer Customer { get; set; }
public Order Order { get; set; }
}
public class Order
{
public int OrderId { get; set; }
public int CustomerId { get; set; }
public List<string> DomenNames { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Telephone { get; set; }
public string Email { get; set; }
}
Controller:
private OrderView ov;
public ActionResult Index()
{
return View(ov);
}
[HttpPost]
public ActionResult Index(OrderView model, FormCollection collection) {
return View("done");
}
public ActionResult BlankEditorRow(OrderView model) {
ov = model;
ov.Order.DomenNames.Add("");
return View("Index",ov) ;
}
View:
#using (Html.BeginForm("Index","Order",FormMethod.Post, new {id = "createOrder"})) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Order</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Order.DomenNames)
</div>
#for(int i = 0; i < Model.Order.DomenNames.Count; i++) {
<div>
#Html.EditorFor(item => item.Order.DomenNames[i])
</div>
}
<button type="button" id="b1" onclick="setallert()" >Click me</button>
...
and script:
<script type="text/javascript">
function setallert() {
$.ajax({
url: "Order/BlankEditorRow",
data: $('#createOrder').serialize(),
cache: false,
success: function (data) {
...?
}
});
};
</script>
it goes fine to pass model to controller and while debugging through view I can see that model is changed, but in some case it nothing happen in view. It looks like old model is in place.
I have solved my problem. I post my solution in case some one need it:
Controller:
public ActionResult BlankEditorRow(OrderView model) {
model.Order.DomenNames.Add("");
return PartialView("Index", model) ;
}
View:
<div class="editor-label">
#Html.LabelFor(model => model.Order.DomenNames)
</div>
<div id="tt">
#{Html.RenderPartial("OrderDN", this.Model);}
</div>
<button type="button" id="addBtn">Click me</button>
Script:
$("#addBtn").click(function () {
$.get('#Url.Action("BlankEditorRow", "Order")', $('#createOrder').serialize(), function (res) {
document.getElementById("tt").innerHTML = res;
});
})
I hope it will be useful to someone

Dropdown ClientSide validation MVC3 not working

public class Encapsulated
{
[Required]
public string CategoryId { get; set; }
}
public class Category
{
public string ID { get; set; }
public string CategoryName { get; set; }
}
public class Test
{
public Encapsulated encapsulated { get; set; }
private IEnumerable<Category> categories;
public IEnumerable<Category> Categories
{
get { return
new List<Category>{new Category{ID="1",CategoryName="abc"}}; }
set { categories = value; }
}
}
#using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "Post" }))
{
#Html.DropDownListFor(
x => x.encapsulated.CategoryId,
new SelectList(Model.Categories, "ID", "CategoryName"),
"-- Please select a category --"
)
#Html.ValidationMessageFor(x => x.encapsulated.CategoryId)
<input type="submit" value="Submit Form" />
}}
Why doesn't client validation work on dropDownList. If I place
[Required]
public string CategoryId { get; set; }
directly inside my Test class and change the view to
#Html.DropDownListFor( x => x.CategoryId,
new SelectList(Model.Categories, "ID", "CategoryName"), "-- Please select a category --" ) #Html.ValidationMessageFor(x => x.CategoryId)
client side validation starts working...

How do I use MVC3 editor templates for lists with add and delete with the Razor viewengine?

How do I use MVC3 editor templates for lists with add and delete?
I have an object:
public class Policy
{
public List<PolicyLine> PolicyLines = new List<PolicyLine>();
}
public class PolicyLine
{
public PolicyLine(bool isPositive, string policyText)
{
IsPositive = isPositive;
PolicyText = policyText;
}
public bool IsPositive { get; set; }
public string PolicyText { get; set; }
}
I have an editorTemplate: in Views\Shared\EditorTemplates\Policy.cshtml and Views\Shared\EditorTemplates\PolicyLine.cshmtml and I'm wondering how to enable users to add and delete PolicyLines from the Policy?
For the DELETE, just add the following line to the PolicyLine.cshtml and add a Delete Action to your Controller to perform the delete.
#Html.ActionLink("Delete", "Delete", new { id = #Model.PolicyID })
The ADD is a bit trickier, you could add button to you Policy.cshtml and then call some javascript to insert some html on the fly.
OR
You could have the button display a new page to capture the new policyline and then return to the original page with the new line added.
I got this to work for me:
Here is my Views/Policy/Index.cshtml
#using (Html.BeginForm("Submit", "Policy")) {
<fieldset>
#Html.EditorForModel()
</fieldset>
}
Here is my Views/Shared/EditorTemplates/Policy.cshtml
#model Policy
<br />
<label for="IsPositive">Is positive?</label>
#Html.CheckBox("IsPositive")
<input type="text" name="PolicyText" />
<input type="submit" value="Add to Policy" title="SubmitFromReferalPolicy" />
#Html.EditorFor(a => a.PolicyLines)
Here is my Views/Shared/EditorTemplates/PolicyLine.cshtml
#model PolicyLine
<br />
#this.Model.ToString()
#Html.ActionLink("Delete", "DeleteLine/" + Model.Identifier.ToString())
Here is my Policy.cs
public class Policy
{
public string Id { get; set; }
public List<PolicyLine> PolicyLines = new List<PolicyLine>();
public override string ToString()
{
return PolicyFormatter.FormatPolicy(this);
}
}
Here is my PolicyLine.cs
public class PolicyLine
{
public bool IsPositive { get; set; }
public string PolicyText { get; set; }
public Guid Identifier { get; set; }
public override string ToString()
{
return PolicyFormatter.FormatPolicyLine(this);
}
}
Here is my add method from PolicyController.cs
[HttpPost]
public ActionResult Submit(PolicyLine submitted)
{
Policy saveMe = Policy.GetPolicyFromUserName(UserName);
submitted.Identifier = Guid.NewGuid();
saveMe.PolicyLines.Add(submitted);
Store.Write(saveMe);
return RedirectToAction("Index");
}
Here is my delete method from PolicyController.cs
public ActionResult DeleteLine(Guid identifier)
{
Policy saveMe = Policy.GetPolicyFromUserName(UserName);
PolicyLine removeMe = saveMe.PolicyLines.Find(p => p.Identifier == identifier);
saveMe.PolicyLines.Remove(removeMe);
Store.Write(saveMe);
return RedirectToAction("Index");
}

Resources