I am trying to save list of object from view to controller but i am getting NullReferenceException when list is more that 25. It works fine if list less than 25.
public async Task<IActionResult> ImportStudentExcel(IFormFile file)
{
var list = new List<StudentImport>();
//Here it contains logic for adding item to list from excel file
ViewBag.FileName = file.FileName;
return View(list.ToList());
}
I am getting all the item in my view
I am doing this to bind properties
//Containes Table for Showing List
<form id="saveForm" asp-action="SaveFromImport" asp-controller="StudentImport" method="POST">
<input type="hidden" name="filename" value="#ViewBag.FileName">
#for(int i=0; i<Model.Count; i++)
{
<input asp-for="#Model[#i].Fullname" type="hidden" value="#Model[#i].Fullname"/>
<input asp-for="#Model[#i].Gender" type="hidden" value="#Model[#i].Gender"/>
<input asp-for="#Model[#i].DOB" type="hidden" value="#Model[#i].DOB"/>
// Other 15 Properties Like Address, PhoneNumber, RegNo etc
}
<input type="submit" value="Save">
</form>
When I inspect this page all item are present
public async Task<IActionResult> SaveFromImport(List<StudentImport> students, string filename)
{
try
{
foreach (var t in students)
{
System.Console.WriteLine(t.Fullname);
//Save to DB
}
}
catch (Exception e)
{
System.Console.WriteLine(e.ToString());
}
return RedirectToAction("Index", "Student");
}
Am getting NullReference at foreach Statement. I dont know whats going on. It works as expected when list count is 13 but wont work when count is 25 or more, It also works when there is only one property in StudentImportModel and count is sttil 25.
The ExceptionMessage in my case was NullReferenceException but the actual error was InvalidDataException: Form value count limit 1024 exceeded.
However, I managed to solve this by adding this code in ConfigureServices method.
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = 6000;
});
Related
Problem
I've often used this kind of computed properties where the setter simply returns the new value :
#computed('args.myValue')
get myValue() {
return this.args.myValue;
}
set myValue(newValue) {
return newValue; // <==== this is no longer valid with native setter
}
This does few things :
Set initial value to args.myValue
Allow to change the value (typically through an <Input #value={{this.myValue}} />)
Restore the default value when args.myValue changes
The problem comes with native setters which can't return any value.
Notice I could probably find a "hackish" solution but I'd like to have code that follows new EmberJS conventions in order to avoid painfull later updates.
Things I tried
Manual caching
#tracked _myValue = null;
get myValue() {
return this._myValue || this.args.myValue;
}
set myValue(newValue) {
this._myValue = newValue;
}
This does not work because _myValue is always set after the first myValue=(newValue).
In order to make it work, there should be some kind of observer which resets it to null on args.myValue change.
Sadly, observers are no longer part of EmberJS with native classes.
{{unbound}} helper
<Input #value={{unbound this.myValue}} />
As expected, it does not work because it just doesn't update myValue.
{{unbound}} helper combined with event.target.value handling
<Input #value={{unbound this.myValue}} {{on "keyup" this.keyPressed}} />
get myValue() {
return this.args.myValue;
}
#action keyPressed(event) {
this.doStuffThatWillUpdateAtSomeTimeMyValue(event.target.value);
}
But the Input is still not updated when the args.myValue changes.
Initial code
Here is a more concrete use example :
Component
// app/components/my-component.js
export default class MyComponent extends Component {
#computed('args.projectName')
get projectName() {
return this.args.projectName;
}
set projectName(newValue) {
return newValue; // <==== this is no longer valid with native setter
}
#action
searchProjects() {
/* event key stuff omitted */
const query = this.projectName;
this.args.queryProjects(query);
}
}
{{! app/components/my-component.hbs }}
<Input #value={{this.projectName}} {{on "keyup" this.searchProjects}} />
Controller
// app/controllers/index.js
export default class IndexController extends Controller {
get entry() {
return this.model.entry;
}
get entryProjectName() {
return this.entry.get('project.name');
}
#tracked queriedProjects = null;
#action queryProjects(query) {
this.store.query('project', { filter: { query: query } })
.then((projects) => this.queriedProjects = projects);
}
#action setEntryProject(project) {
this.entry.project = project;
}
}
{{! app/templates/index.hbs }}
<MyComponent
#projectName={{this.entryProjectName}}
#searchProjects={{this.queryProjects}} />
When the queriedProjects are set in the controller, the component displays them.
When one of those search results is clicked, the controller updates the setEntryProject is called.
According to this Ember.js discussion :
Net, my own view here is that for exactly this reason, it’s often better to use a regular <input> instead of the <Input> component, and to wire up your own event listeners. That will make you responsible to set the item.quantity value in the action, but it also eliminates that last problem of having two different ways of setting the same value, and it also gives you a chance to do other things with the event handling.
I found a solution for this problem by using standard <input>, which seems to be the "right way" to solve it (I'll really appreciate any comment that tells me a better way) :
{{! app/components/my-component.hbs }}
<input value={{this.projectName}} {{on "keyup" this.searchProjects}} />
// app/components/my-component.js
#action
searchProjects(event) {
/* event key stuff omitted */
const query = event.target.value;
this.args.queryProjects(query);
}
If I needed to keep the input value as a property, I could have done this :
{{! app/components/my-component.hbs }}
<input value={{this.projectName}}
{{on "input" this.setProjectQuery}}
{{on "keyup" this.searchProjects}} />
// app/components/my-component.js
#action setProjectQuery(event) {
this._projectQuery = event.target.value;
}
#action
searchProjects( {
/* event key stuff omitted */
const query = this._projectQuery;
this.args.queryProjects(query);
}
EDIT
Notice the following solution has one downside : it does not provide a simple way to reset the input value to the this.projectName when it does not change, for example after a focusout.
In order to fix this, I've added some code :
{{! app/components/my-component.hbs }}
<input value={{or this.currentInputValue this.projectName}}
{{on "focusin" this.setCurrentInputValue}}
{{on "focusout" this.clearCurrentInputValue}}
{{on "input" this.setProjectQuery}}
{{on "keyup" this.searchProjects}} />
// app/components/my-component.js
// previous code omitted
#tracked currentInputValue = null;
#action setCurrentInputValue() {
this.currentInputValue = this.projectName;
}
#action clearCurrentInputValue() {
this.currentInputValue = null;
}
There is a quite generic and concise approach to this 2-source binding scenario with any interactive input element and beyond.
Considering your first attempt (»Manual Caching«):
we have a functional feedback loop through the getter and setter; no return value from the setter is required since it unconditionally triggers a bound getter (this._myValue doesn't need to be tracked)
a switch is needed to let a changing external preset value (this.args.myValue) inject into this loop
this is accomplished by a GUID hashmap based on the preset value that establishes a transient scope for the interactive input; thus, changing preset value injections and interative inputs overwrite each other:
// app/components/my-component.js
import Component from '#glimmer/component';
import { guidFor } from '#ember/object/internals';
export default class extends Component {
// external preset value by #stringArg
_myValue = new Map();
get myValue() {
let currentArg = this.args.stringArg || null;
let guid = guidFor(currentArg);
if (this._myValue.has(guid)) {
return this._myValue.get(guid)
}
else {
this._myValue.clear(); // (optional) avoid subsequent GUID reuse of primitive types (Strings)
return currentArg;
}
}
set myValue(value) {
this._myValue.set(guidFor(this.args.stringArg || null), value);
}
}
// app/components/my-component.hbs
<Input #value={{mut this.myValue}} />
https://ember-twiddle.com/a72fa70c472dfc54d03d040f0d849d17
In grails, I am trying to get a list of checked check boxes.
I have the list of check boxes, but my issues are two:
1) when I click on a single item in the list and click submit - I only get the value "on". If I click more than one check box item, I get something like this:
[Ljava.lang.String;#5a37f9f7
2). I do not get a list or the name of the item checked.
Here is my code for the check boxes in the gsp:
<g:form action="submitForm">
<ul class="columns3">
<g:each in="${name}" var="fileName" >
<g:checkBox value="${false}" name="${ 'fileName'}" /> ${fileName.replaceFirst(~/\.[^\.]+$/, '')}<br>
</g:each>
</ul>
<br>
<br>
<g:submitButton name="Submit"/>
</g:form>
and here is the controller code (groovy):
class Read_dirController {
def index() {
def list = []
def dir = new File("/home/ironmantis/Documents/business/test_files")
dir.eachFileRecurse (FileType.FILES) { file ->
list << file
}
list.each {
println it.name.replaceFirst(~/\.[^\.]+$/, '')
}
render(view: "index", model: [name:list.name])
params.list('fileName')
}
def displayForm() { }
def submitForm(String fileName) {
render fileName
//render(view: "tests_checked", fileName)
}
}
I tried to bind an id to the check boxes, but I keep getting an exception error.
Any help you can give I truly appreciate it; I am new to grails.
ironmantis7x
You can use the beautiful command object for this. For this ,first make a class RequestCO having the boolean fields.
class RequestCO {
boolean isChecked;
String name;
}
And
class RequestParentCO {
List<RequestCO> requestCOs = [].withLazyDefault { new RequestCO() }
}
Now you just simply bind all your request to RequestParentCO in your action:
def submitForm(RequestParentCO parentCO) {
println parentCO.requestCOs.findAll { it.isChecked }
}
This will give you all the checked checkboxes results.
GSP
<g:form action="process">
<ul class="columns3">
<g:each in="${["one", "two", "three"]}" var="fileName" status="i">
<g:hiddenField name="requestCOs[${i}].name" value="${fileName}"/>
<g:checkBox name="requestCOs[${i}].isChecked"/> ${fileName}<br>
</g:each>
</ul>
<g:submitButton name="Submit"/>
This way,
def submitForm() {
def values = request.getParameterValues("fileName")
//here values contains string array which are selected in checkbox
}
you can use request.getParameterValues("fileName") method, this will give selected checkbox in string array
I writing some code with C# and MVC and I have button for sorting a list of data by asc and desc. The logic works in my controller, I am able to call the method that sorts the list and in the breakpoint I can see that it has been sorted.
But it's weird because when I loop through my list in the partial view it never works. I use a breakpoint in my view to make sure it's the same order of items which it is. But it's like the new values don't render to the screen.
TeamManagement.cshtml
#model Website.Models.modelTeamSelect
#{
ViewBag.Title = "Football App";
}
#section featured {
}
#using (Ajax.BeginForm("_PartialTeams",
new
{
model = this.Model
},
new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "divCreatedTeams",
InsertionMode = InsertionMode.Replace
}))
{
<div id="divTeams" style="float: left; padding: 10px;">
<h3>Create a new team:</h3>
#Html.LabelFor(m => m.team.TeamName)
#Html.TextBoxFor(m => m.team.TeamName)
<input type="submit" value="Add Team" name="btnSubmit" />
</div>
Html.RenderPartial("~/Views/Partials/_PartialTeams.cshtml");
}
_PartialTeams.cshtml
#model Website.Models.modelTeamSelect
<div id="divCreatedTeams" style="float: left; padding: 10px;">
<h3>Your created teams:</h3>
<input type="submit" value="Asc" name="btnSubmit" />
<input type="submit" value="Desc" name="btnSubmit" />
<br />
#if (Model.teams.Count > 0)
{
for (int i = 0; i < Model.teams.Count; i++)
{
#Html.EditorFor(m => m.teams[i].TeamName)
<input type="button" value="Update team name" name="btnSubmit"/>
<input type="button" value="Remove team" name="btnSubmit"/>
<br />
}
}
</div>
Sorting logic in my controller
[HttpPost]
public PartialViewResult _PartialTeams(string BtnSubmit, modelTeamSelect modelTeamSelect)
{
switch (BtnSubmit)
{
case "Add Team":
modelTeamSelect.teams.Add(modelTeamSelect.team);
break;
case "Asc":
FootballRepository = new Repository.FootballRepository();
modelTeamSelect.teams = FootballRepository.Sort(modelTeamSelect, BtnSubmit);
break;
case "Desc":
FootballRepository = new Repository.FootballRepository();
modelTeamSelect.teams = FootballRepository.Sort(modelTeamSelect, BtnSubmit);
break;
}
return PartialView("~/Views/Partials/_PartialTeams.cshtml", modelTeamSelect);
}
public List<Models.modelTeam> Sort(Models.modelTeamSelect modelTeamSelect, string sort)
{
switch (sort)
{
case "Asc":
modelTeamSelect.teams = modelTeamSelect.teams.OrderBy(t => t.TeamName).ToList();
break;
case "Desc":
modelTeamSelect.teams = modelTeamSelect.teams.OrderByDescending(t => t.TeamName).ToList();
break;
}
return modelTeamSelect.teams;
}
My main model with team collection
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Website.Models
{
public class modelTeamSelect
{
public modelTeamSelect()
{
teams = new List<modelTeam>();
team = new modelTeam();
}
public List<modelTeam> teams { get; set; }
public modelTeam team { get; set; }
}
}
My method Sort does it's job but in the view it never displays correctly. e.g. always wrong order.
Anyone have any ideas because I am stuck.
Screenshots
In the screenshots I click sort by Asc and you can see it says Newcastle as the first item in the list. But when the page renders it will say West Ham first even though it is iterating using the for loop.
All the Html helpers are preferring to use the ModelState values over the actual model values.
So even you have sorted in place your modelTeamSelect.teams in your action in the view #Html.EditorFor(m => m.teams[i].TeamName) call will use the original (before sorting) values form the ModelState.
The solution: if you are updating your action parameters in-place then just clear the ModelState before returning the View/PartialView:
[HttpPost]
public PartialViewResult _PartialTeams(string BtnSubmit,
modelTeamSelect modelTeamSelect)
{
// ... Do the sorting, etc.
ModelState.Clear();
return PartialView("~/Views/Partials/_PartialTeams.cshtml", modelTeamSelect);
}
You can read more about why the helpers are working like this in this article: ASP.NET MVC Postbacks and HtmlHelper Controls ignoring Model Changes
i am relatively new in django and angualarJs.The problem is that angularJs is not responding the get method properly.I have a webpage developed by django where i have a search field.For the execution of search i use a angularJs functionality that is ng-submit and write angularJs code to return value using get method.May be i made a mistake here.you can see my code... here is my template which containing the angularJs also...
<div class="navbar navbar-default " ng-controller="NavCtrl">
<form action="" class="navbar-form navbar-right" ng-submit="search()">
<input class="form-control col-lg-8" type="text" placeholder="Search" ng-model="term"></input>
</form>
</div>
<script>
app.controller("NavCtrl", ['$scope', '$http', '$location', '$q', '$timeout',
function NavCtrl($scope, $http, $location, $q, $timeout) {
$scope.results = ["Test"];
$scope.term = "";
$scope.reqs = "5";
$scope.pics = "45";
$scope.ddata = "asdasd";
$scope.ddata = $http.post("{% url 'get-nav-info' %}").success(
function (result) {
//$scope.reqs = result.data.data.num_request;
//$scope.pics = result.data.data.num_photo;
return result.data;
}
);
//$scope.reqs = $scope.ddata.num_request;
//$scope.pics = $scope.ddata.num_photo;
$scope.search = function () {
//alert("test");
//$location.absUrl("{% url 'search-term-show' %}").search({'term':$scope.term}).apply();
//$location.path("{% url 'search-term-show' %}").search({'term':$scope.term}).apply();
$http.get("{% url 'search-term-show' %}?term=" + $scope.term).success(function (result) {
return result.data;
});
//$scope.$apply();
}
}
]);
</script>
now the problem is that while i press enter ,there is no result,but if i manually write this URL which is http://www.kothay.com/searchphoto/?term=a in the address bar then the result is showing .In mention,this url is the that url which should be appear in the address bar when i press the enter to search my photos.But with the enter press its not appearing in the address bar and that's why the results are not showing.I hope you can understand what i am trying to say.May be there is a mistake in my code.Please help me to fix this problem.
You are doing thing wrong.
1st, the success is a defer of get, so return result.data and returns it to the get deferred and there it goes to the heaven. So if you would like to keep the current architecture it should look more like this
$scope.search = [];
getsearch = function () {
$http.get("{% url 'search-term-show' %}?term=" + $scope.term).success(function (result) {
$scope.search = result.data;
});
};
getsearch();
2nd that can still not update your UI cuz if the ctrl function is over and the digest is over before your response it wont update your UI cuz its in another scope (not $scope, but the programmatically term scope). The solution to this is to put your data in a service and in your ctr just do.
function ctrl($scope, myservice){
$scope.data = myservice;
}
ng-repeat="x in data.results"
Here is a full tutorial http://bresleveloper.blogspot.co.il/2013/08/breslevelopers-angularjs-tutorial.html
And last thing its just a good practice to always have .error(...)
This code:
Html.CheckBoxList(ViewData.TemplateInfo.HtmlFieldPrefix, myList)
Produces this mark-up:
<ul><li><input name="Header.h_dist_cd" type="checkbox" value="BD" />
<span>BD - Dist BD Name</span></li>
<li><input name="Header.h_dist_cd" type="checkbox" value="SS" />
<span>SS - Dist SS Name</span></li>
<li><input name="Header.h_dist_cd" type="checkbox" value="DS" />
<span>DS - Dist DS Name</span></li>
<li><input name="Header.h_dist_cd" type="checkbox" value="SW" />
<span>SW - Dist SW Name </span></li>
</ul>
You can check multiple selections. The return string parameter Header.h_dist_cd only contains the first value selected. What do I need to do to get the other checked values?
The post method parameter looks like this:
public ActionResult Edit(Header header)
I'm assuming that Html.CheckBoxList is your extension and that's markup that you generated.
Based on what you're showing, two things to check:
The model binder is going to look for an object named Header with string property h_dist_cd to bind to. Your action method looks like Header is the root view model and not a child object of your model.
I don't know how you are handling the case where the checkboxes are cleared. The normal trick is to render a hidden field with the same name.
Also a nit, but you want to use 'label for="..."' so they can click the text to check/uncheck and for accessibility.
I've found that using extensions for this problem is error prone. You might want to consider a child view model instead. It fits in better with the EditorFor template system of MVC2.
Here's an example from our system...
In the view model, embed a reusable child model...
[AtLeastOneRequired(ErrorMessage = "(required)")]
public MultiSelectModel Cofamilies { get; set; }
You can initialize it with a standard list of SelectListItem...
MyViewModel(...)
{
List<SelectListItem> initialSelections = ...from controller or domain layer...;
Cofamilies = new MultiSelectModel(initialSelections);
...
The MultiSelectModel child model. Note the setter override on Value...
public class MultiSelectModel : ICountable
{
public MultiSelectModel(IEnumerable<SelectListItem> items)
{
Items = new List<SelectListItem>(items);
_value = new List<string>(Items.Count);
}
public int Count { get { return Items.Count(x => x.Selected); } }
public List<SelectListItem> Items { get; private set; }
private void _Select()
{
for (int i = 0; i < Items.Count; i++)
Items[i].Selected = Value[i] != "false";
}
public List<SelectListItem> SelectedItems
{
get { return Items.Where(x => x.Selected).ToList(); }
}
private void _SetSelectedValues(IEnumerable<string> values)
{
foreach (var item in Items)
{
var tmp = item;
item.Selected = values.Any(x => x == tmp.Value);
}
}
public List<string> SelectedValues
{
get { return SelectedItems.Select(x => x.Value).ToList(); }
set { _SetSelectedValues(value); }
}
public List<string> Value
{
get { return _value; }
set { _value = value; _Select(); }
}
private List<string> _value;
}
Now you can place your editor template in Views/Shared/MultiSelectModel.ascx...
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<WebUI.Cofamilies.Models.Shared.MultiSelectModel>" %>
<div class="set">
<%=Html.LabelFor(model => model)%>
<ul>
<% for (int i = 0; i < Model.Items.Count; i++)
{
var item = Model.Items[i];
string name = ViewData.ModelMetadata.PropertyName + ".Value[" + i + "]";
string id = ViewData.ModelMetadata.PropertyName + "_Value[" + i + "]";
string selected = item.Selected ? "checked=\"checked\"" : "";
%>
<li>
<input type="checkbox" name="<%= name %>" id="<%= id %>" <%= selected %> value="true" />
<label for="<%= id %>"><%= item.Text %></label>
<input type="hidden" name="<%= name %>" value="false" />
</li>
<% } %>
</ul>
<%= Html.ValidationMessageFor(model => model) %>
Two advantages to this approach:
You don't have to treat the list of items separate from the selection value. You can put attributes on the single property (e.g., AtLeastOneRequired is a custom attribute in our system)
you separate model and view (editor template). We have a horizontal and a vertical layout of checkboxes for example. You could also render "multiple selection" as two listboxes with back and forth buttons, multi-select list box, etc.
I think what you need is how gather selected values from CheckBoxList that user selected and here is my solution for that:
1- Download Jquery.json.js and add it to your view as reference:
2- I've added a ".cssMyClass" to all checkboxlist items so I grab the values by their css class:
<script type="text/javascript" >
$(document).ready(function () {
$("#btnSubmit").click(sendValues);
});
function populateValues()
{
var data = new Array();
$('.myCssClas').each(function () {
if ($(this).attr('checked')) {
var x = $(this).attr("value");
data.push(x);
}
});
return data;
}
function sendValues() {
var data = populateValues();
$.ajax({
type: 'POST',
url: '#Url.Content("~/Home/Save")',
data: $.json.encode(data),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function () { alert("1"); }
});
}
</script>
3- As you can see I've added all selected values to an Array and I've passed it to "Save" action of "Home" controller by ajax 4- in Controller you can receive the values by adding an array as argument:
[HttpPost]
public ActionResult Save(int[] val)
{
I've searched too much but apparently this is the only solution. Please let me know if you find a better solution for it.
when you have multiple items with the same name you will get their values separated with coma