My angular controller doesnt send data to c# controller - html

Hello everyone,
I couldn't send data from my angular controller to my c# controller.Whenever the controller is called it throws out error callback.I have tried different ways,but i couldn't rectify it.Am i making any mistake in defining correct url.I am really clueless.
Angular controller
var httpTimeout = 1800000;
var httpTimeoutSearch = 3600000;
angular.module('MyApp', [])
var app = angular.module('myApp', []);
app.controller('LoginController', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) {
alert("in");
$scope.Username = "";
$scope.Password = "";
$scope.Login = function () {
if ($scope.Username != null && $scope.username != "") {
if ($scope.Password != null && $scope.password != "") {
try {
var obj = { UserName: $scope.Username, Password: $scope.Password };
alert(obj.Username);
$http({
method: 'POST',
data: obj,
url: '/Account/Maxi',
timeout: httpTimeout,
}).then(function successCallback(response) {
alert("sucess");
}, function errorCallback(response) {
alert("error");
});
}
catch (ex)
{ alert(ex); }
}
}
}
}]);
C# controller
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Maxi(LoginModel data)
{
string strReturn = "";
string ConStr = "";
string Code = "";
if (data.UserName != null)
{
if (data.Password != null)
{
DataSet ds = new DataSet();
SqlParameter[] parameters =
{
new SqlParameter( "#name", SqlDbType.VarChar, 20) { Value = data.UserName } ,
new SqlParameter("#Roll_No", SqlDbType.Int) { Value = data.Password } ,
};
ConStr = "Data Source=" + "192.168.1.9" + ";Initial Catalog=" + "MyFistDataBase" + ";User id=" + "sa" + ";Password=" + "123" + ";";
using (SqlConnection con = new SqlConnection(ConStr))
{
using (SqlCommand cmd = new SqlCommand("Maxi", con))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter();
cmd.Parameters.AddRange(parameters);
da.SelectCommand = cmd;
da.Fill(ds);
}
}
string errmsg = "";
if (errmsg != "")
{
Code = "0"; strReturn = errmsg;
}
else
{
if (ds.Tables.Count > 0)
{
if (ds.Tables[0].Rows.Count > 0)
{
Code = "1";
foreach (DataRow dr in ds.Tables[0].Rows)
{
strReturn += dr[0].ToString();
}
if (strReturn == "1")
{
Console.Write("Updated");
}
}
//TripDT = TripDT.ToShortDateString();
}
}
}
}
return View(data);
}
Object Model
public class LoginModel
{
[Key]
public string UserName { get; set; }
public string Password { get; set; }
}

You are misspelling the sending KVP data.
var obj = { Username: $scope.Username, Passord: $scope.Password };
should be
var obj = { UserName: $scope.Username, Password: $scope.Password };
for verificationToken error need to add this data to json also
"__RequestVerificationToken" : your_html_value
see how to add this key data HERE in Detail

Related

asynchronous behavior of functions in typescript

I implemented this snippet of code:
var tmpString = null;
this.restProvider.validateUser(this.registerCredentials.email, this.registerCredentials.password)
.then(data => {
tmpString = JSON.stringify(data);
});
console.log(tmpString);
But, despite data is not null, console print a null value and tmpString is set to the right value after a short time. How I can solve that problem? Thanks
The real function is:
registerNewUser()
{
var tmpString = null;
this.restProvider.validateUser(this.registerCredentials.email, this.registerCredentials.password)
.then(data => {
tmpString = JSON.stringify(data);
});
console.log(tmpString);
if(tmpString == "false")
{
return false;
}
else
{
this.registerCredentials.email = JSON.parse(tmpString).email;
this.registerCredentials.password = JSON.parse(tmpString).password;
this.email = JSON.parse(tmpString).email;
this.password = JSON.parse(tmpString).password;
}
return this.email + this.password;
}
and I use it
public login() {
this.showLoading();
this.registerNewUser();
if(this.email == "false" && this.password == "false")
{
this.showError("Access Denied");
}
else
{
this.auth.login(this.registerCredentials);
this.showError("Access Permit");
}
}
I resolved doing that
registerNewUser()
{
var tmpString = null;
this.restProvider.validateUser(this.registerCredentials.email, this.registerCredentials.password)
.then(data => {
tmpString = JSON.stringify(data);
if(tmpString == "false")
{
this.showError("Access Denied");
}
else
{
this.registerCredentials.email = JSON.parse(tmpString).email;
this.registerCredentials.password = JSON.parse(tmpString).password;
this.email = JSON.parse(tmpString).email;
this.password = JSON.parse(tmpString).password;
this.auth.login(this.registerCredentials);
this.showError("Access Permit");
}
});
}
But is this the right solution?
Taking into account the below code (commented with line numbers):
var tmpString = null; // 1
this.restProvider.validateUser(this.registerCredentials.email, this.registerCredentials.password)
.then(data => {
tmpString = JSON.stringify(data); // 2
});
console.log(tmpString); // 3
The order of execution is:
line 1
line 3
line 2
That's because when line 3 is reached, the asynchronous request hasn't finished. So in order to print tmpString properly, move the console.log(tmpString); after line 2, inside the callback (when the response arrived), like this:
var tmpString = null; // 1
this.restProvider.validateUser(this.registerCredentials.email, this.registerCredentials.password)
.then(data => {
tmpString = JSON.stringify(data); // 2
console.log(tmpString); // 3
});

VueJs Axios Post FormData Parameters

We are using Vue in our frontend application, and for one of our REST service our backend server(using spring and java) expects to have the below data structure:
public class MAProductsUploadRequest
{
public List<MAProductUploadRequest> products;
}
public class MAProductUploadRequest {
public String productName;
public String productDescription;
public double productPrice;
public int productOrder;
public MultipartFile productImage=null;
public double cropX;
public double cropY;
public double cropWidth;
public double cropHeight;
public int categoryId;
}
And in our Vuejs application we tried to post the data as in the below code:
addProducts: function () {
console.log("Add Products Working. Total Product Count:"+this.excelProducts.length);
let header = {
headers: auth.getAuthHeader()
};
let formData = new FormData();
for (let i=0;i<this.excelProducts.length;i++ ) {
console.log("Starting loop:"+i);
var prod = this.excelProducts[i];
console.log("Product Before:"+prod);
if (document.getElementById('photo-image-'+i) !== null) {
if(document.getElementById('photo-image-'+i).files.length !== 0) {
console.log("Getting Image For Prod");
prod.productImage = document.getElementById('photo-image-'+i).files[0] ;
}
}
prod.cropX = this.cropProp.x;
prod.cropY = this.cropProp.y;
prod.cropWidth = this.cropProp.width;
prod.cropHeight = this.cropProp.height;
prod.rotate = this.cropProp.rotate;
console.log("Product After:"+prod);
formData.append("products[]",prod);
}
for (var pair of formData.entries()) {
console.log(pair[0]+ ', ' + pair[1]);
}
//console.log("Form Data:"+formData.products);
if (formData.products !== null) {
axios.post(`${API_URL}/company/uploadProducts`, formData, header).then((response) => {
logForDevelopment(response);
this.getProducts();
this.product = {
id: '',
name: '',
description: '',
price: '',
photo: '',
isEdit: false
};
this.excelProducts = [];
this.isPhotoChosen = false;
this.isPhotosChosen = [];
this.cropImg = '';
document.getElementById('photo-image').value = null;
this.isLoading = false;
}).catch((error) => {
this.isLoading = false;
if(error.response) {
logForDevelopment(error);
document.getElementById('photo-image').value = null;
if(error.response.status === 401 || error.response.status === 403) {
auth.afterInvalidToken('login');
}
}
})
} else {
console.log("Form Data Is Empty");
}
},
But when we use this code (even if the photo-image was null) the backend server returns HTTP 500 error. Because the products array seems null.
I wasn't able to figure it out where the problem may be in the Vuejs code?
EDIT: (I'VE also tried the below code but the still same result)
addProducts: function () {
console.log("Add Products Working. Total Product Count:"+this.excelProducts.length);
let header = {
headers: auth.getAuthHeader()
};
let formData = new FormData();
let prods = [];
for (let i=0;i<this.excelProducts.length;i++ ) {
console.log("Starting loop:"+i);
let prod = this.excelProducts[i];
let subFormData = new FormData();
subFormData.append("productName",prod.productName);
subFormData.append("productDescription",prod.productDescription);
subFormData.append("productPrice",prod.price);
subFormData.append("categoryId",prod.categoryId);
subFormData.append("cropX",this.cropProp.x);
subFormData.append("cropY",this.cropProp.y);
subFormData.append("cropWidth",this.cropProp.width);
subFormData.append("cropHeight",this.cropProp.height);
prods.push(subFormData);
if (document.getElementById('photo-image-'+i) !== null) {
if(document.getElementById('photo-image-'+i).files.length !== 0) {
console.log("Getting Image For Prod");
subFormData.productImage = document.getElementById('photo-image-'+i).files[0] ;
}
}
}
formData.append("products",prods);
console.log("Form Data:"+formData);
if (formData.products !== null) {
axios.post(`${API_URL}/company/uploadProducts`, formData, header).then((response) => {
logForDevelopment(response);
this.getProducts();
this.product = {
id: '',
name: '',
description: '',
price: '',
photo: '',
isEdit: false
};
this.excelProducts = [];
this.isPhotoChosen = false;
this.isPhotosChosen = [];
this.cropImg = '';
document.getElementById('photo-image').value = null;
this.isLoading = false;
}).catch((error) => {
this.isLoading = false;
if(error.response) {
logForDevelopment(error);
//document.getElementById('photo-image').value = null;
if(error.response.status === 401 || error.response.status === 403) {
auth.afterInvalidToken('login');
}
}
})
} else {
console.log("Form Data Is Empty");
}
},
What I'm actually trying to achive is, our below code works fine when sending single product info to our backend service, but I want to make it an array so send multiple products at once:
addProduct: function () {
let header = {
headers: auth.getAuthHeader()
};
let formData = new FormData();
formData.append('productName', this.product.name);
formData.append('productDescription', this.product.description === '' ? "" : this.product.description);
formData.append('productPrice', this.product.price);
formData.append('categoryId', this.product.categoryId);
if(document.getElementById('photo-image').files.length !== 0) {
formData.append('productImage', document.getElementById('photo-image').files[0]);
}
formData.append('cropX', this.cropProp.x);
formData.append('cropY', this.cropProp.y);
formData.append('cropWidth', this.cropProp.width);
formData.append('cropHeight', this.cropProp.height);
formData.append('rotate', this.cropProp.rotate);
console.log(formData);
axios.post(`${API_URL}/company/products`, formData, header).then((response) => {
logForDevelopment(response);
this.getProducts();
this.product = {
id: '',
name: '',
description: '',
price: '',
photo: '',
isEdit: false
};
this.isPhotoChosen = false;
this.cropImg = '';
document.getElementById('photo-image').value = null;
this.isLoading = false;
}).catch((error) => {
this.isLoading = false;
if(error.response) {
logForDevelopment(error);
document.getElementById('photo-image').value = null;
if(error.response.status === 401 || error.response.status === 403) {
auth.afterInvalidToken('login');
}
}
})
},
Does anyone have any idea about that?
You can also look at the screenshot of my application in below(I want to send all the items in screenshot , at once )
Your issue is probably il the formData.append("products[]",prod) method of your FormData class, try changing formData.append("products[]",prod) with formData.products.push(prod).
Furthermore in your axios call the payload should be formData.products if you API endpoint expects the products right?
Try axios.post(${API_URL}/company/uploadProducts, formData.products, header).
I do not see any syntax issue relative to Vue, hope this helps. (And of course check what is sent by XHR in devtools as suggested in the comments)

How can I add shoping cart with ajax functionality under single product page?

I want to add shoping cart under single product page (below add to cart button) how I can do this in Magento 1.9?
Use the following code to solve your query:
open: template\catalog\product\view.phtml
Find:
productAddToCartForm.submit = function(button, url) {
if (this.validator.validate()) {
var form = this.form;
var oldUrl = form.action;
if (url) {
form.action = url;
}
var e = null;
try {
this.form.submit();
} catch (e) {
}
this.form.action = oldUrl;
if (e) {
throw e;
}
if (button && button != 'undefined') {
button.disabled = true;
}
}
}.bind(productAddToCartForm);
Replace with :
productAddToCartForm.submit = function(button, url) {
if (this.validator.validate()) {
var form = this.form;
var oldUrl = form.action;
if (url) {
form.action = url;
}
var e = null;
//Start of our new ajax code
if(!url){
url = jQuery('#product_addtocart_form').attr('action');
}
var data = jQuery('#product_addtocart_form').serialize();
data += '&isAjax=1';
jQuery('#ajax_loader').show();
try {
jQuery.ajax({
url: url,
dataType: 'json',
type : 'post',
data: data,
success: function(data){
jQuery('#ajax_loader').hide();
alert(data.status + ": " + data.message);
}
});
} catch (e) {
}
//End of our new ajax code
this.form.action = oldUrl;
if (e) {
throw e;
}
}
}.bind(productAddToCartForm);
Open : catalog/product/view/addtocart.phtml
Find :
" class="button btn-cart" onclick="productAddToCartForm.submit(this)">
Replace with :
" class="button btn-cart" onclick="productAddToCartForm.submit(this)">
getSkinUrl('images/opc-ajax-loader.gif')?>'/>
Open: app\code\core\Mage\Checkout\controllers\CartController.php
Find : $params = $this->getRequest()->getParams(); in addAction() function
After the above line, place this code :
if($params['isAjax'] == 1){
$response = array();
try {
if (isset($params['qty'])) {
$filter = new Zend_Filter_LocalizedToNormalized(
array('locale' => Mage::app()->getLocale()->getLocaleCode())
);
$params['qty'] = $filter->filter($params['qty']);
}
$product = $this->_initProduct();
$related = $this->getRequest()->getParam('related_product');
/**
* Check product availability
*/
if (!$product) {
$response['status'] = 'ERROR';
$response['message'] = $this->__('Unable to find Product ID');
}
$cart->addProduct($product, $params);
if (!empty($related)) {
$cart->addProductsByIds(explode(',', $related));
}
$cart->save();
$this->_getSession()->setCartWasUpdated(true);
/**
* #todo remove wishlist observer processAddToCart
*/
Mage::dispatchEvent('checkout_cart_add_product_complete',
array('product' => $product, 'request' => $this->getRequest(), 'response' => $this->getResponse())
);
if (!$this->_getSession()->getNoCartRedirect(true)) {
if (!$cart->getQuote()->getHasError()){
$message = $this->__('%s was added to your shopping cart.', Mage::helper('core')->htmlEscape($product->getName()));
$response['status'] = 'SUCCESS';
$response['message'] = $message;
}
}
} catch (Mage_Core_Exception $e) {
$msg = "";
if ($this->_getSession()->getUseNotice(true)) {
$msg = $e->getMessage();
} else {
$messages = array_unique(explode("\n", $e->getMessage()));
foreach ($messages as $message) {
$msg .= $message.'<br/>';
}
}
$response['status'] = 'ERROR';
$response['message'] = $msg;
} catch (Exception $e) {
$response['status'] = 'ERROR';
$response['message'] = $this->__('Cannot add the item to shopping cart.');
Mage::logException($e);
}
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($response));
return;
}

understanding $http service

I don't understand how the $http service works. I have a controller that calls a factory and the factory calls a WS function.
If I run the app on debug mode, the factory calls the WS function and the WS function returned what I suppose is an json object.
On the other hand, when I watch in the web console, I get a message "undefined".
What should return the WS function? Or what's wrong in my factory?
Thanks in advance.
This is the VB.Net Web Service function:
<ScriptMethod(ResponseFormat:=ResponseFormat.Json, XmlSerializeString:=False)> _
<WebMethod()> _
Public Function getLogin(ByVal email As String, ByVal password As String) As String
Dim dt As New Data.DataTable
Dim result As String = ""
Using con As New SqlConnection(sConn)
'Dim sql As String = "Select id_usuario, nombre_usuario id_tipo_usuario from binder_usuarios where email = #email and password = #password"
Dim sql As String = "Select * from binder_usuarios where email = #email and password = #password"
Dim cmd As New SqlCommand
cmd.CommandText = sql
cmd.Connection = con
cmd.Parameters.AddWithValue("#email", email)
cmd.Parameters.AddWithValue("#password", password)
Dim dataAdapter As New SqlDataAdapter(cmd)
dataAdapter.Fill(dt)
If dt.Rows.Count > 0 Then
result = JsonConvert.SerializeObject(dt, New JavaScriptDateTimeConverter())
Return result
Else
result = "e"
End If
Return result
End Using
End Function
the WS function return a string:
"[{"id_usuario":3,"nombre_usuario":"Quethzel","apellido_paterno":"Diaz","apellido_materno":"Zarate","id_area":1,"id_tipo_usuario":1,"password":"sa","email":"hqdiaz#lis.com.mx"}]"
this is the factory:
function fcQAuth($http, $q, $window) {
return {
loginAuth: function(credentials) {
$http.post('../ws/wsReact.asmx/getLogin', credentials)
.success(function(data, status) {
return "your data it's Ok, in da face !";
})
.error(function(data, status) {
return "don't give up Nigga";
});
//return "myUser. " + credentials.email + ", myPass." + credentials.password;
}
}
}; // end fcQAuth factory
And this is the controller, that call the factory:
function loginCtrl($scope, $q, $http, $location, fcQAuth) {
$scope.loginUser = function() {
var credentials = {
email: $scope.user.email === '' || $scope.user.email === undefined ? 0 : $scope.user.email,
password: $scope.user.password === '' || $scope.user.password === undefined ? 0 : $scope.user.password
};
$scope.userInfo = fcQAuth.loginAuth(credentials);
console.log($scope.userInfo);
};
};
The http.post is an asyncronous call, when the console.log in your controller is executed, the http.post has no returned yet. Try this:
Return the promise in your factory:
function fcQAuth($http, $q, $window) {
return {
loginAuth: function(credentials) {
return $http.post('../ws/wsReact.asmx/getLogin', credentials);
}
};
}
Get the data in the success callback in your controller:
function loginCtrl($scope, $q, $http, $location, fcQAuth) {
var credentials = {
email: $scope.user.email === '' || $scope.user.email === undefined ? 0 : $scope.user.email,
password: $scope.user.password === '' || $scope.user.password === undefined ? 0 : $scope.user.password
};
fcQAuth.loginAuth(credentials).then(function(data){
$scope.userInfo = data;
console.log($scope.userInfo);
});
};

kendo grid not binding data correctly

I have a mvc application with a kendo Grid
Here's the view code
#using Domain.Agromilieu2.Wui.Resources.Bedrijfsgegevens.Views
#using Domain.Agromilieu2.Wui.Models.BeheerTeksten
#model TekstenViewModel.Main
#{
Layout = WebCore.Views.Layouts.Extended;
}
<h2>Teksten</h2>
#(Html.Kendo().Window()
.Name("alertWindow")
.Title("Status Message from Server")
.Draggable()
.Resizable()
.Width(400)
.Height(200)
.Modal(true)
.Visible(false)
.Actions(actions => actions.Close())
)
#Html.WebCore().Popup.CustomButtons("popupDemo", "Waarde", Html.Kendo().Editor().Name("waardeEditor").HtmlAttributes(new { #class = "editorStyle" }).Tools(tools => tools
.Clear()
.Bold().Italic().Underline().Strikethrough()
.JustifyLeft().JustifyCenter().JustifyRight().JustifyFull()
.InsertUnorderedList().InsertOrderedList()
.Outdent().Indent()
.CreateLink().Unlink()
.InsertImage()
.SubScript()
.SuperScript()
.TableEditing()
.ViewHtml()
.Formatting()
.FontName()
.FontSize()
.FontColor().BackColor()
).ToHtmlString(), new[]{new PopupButton("popupDemoAnnuleren", "Cancel", false),new PopupButton("popupDemoOk", "OK")})
<div class="infoPanel">
<div id='divSousMenu'>
<div>
<h2 class="zoekCriteria">ZOEKCRITERIA</h2>
<h4 class="resourceSet">Resource Set:</h4>
#(Html.Kendo().ComboBoxFor(model => model.Filter.userName)
.Name("resourcesSetComboBox")
.DataTextField("Naam")
.DataValueField("ID")
.Filter(FilterType.Contains)
.HtmlAttributes(new { #class = "comboStyle" })
.DataSource(source =>
{
source.Read(read =>
{
read.Action(MVC.BeheerTeksten.ActionNames.ResourceSetsIntoCombo_Read, MVC.BeheerTeksten.Name)
.Data("onAdditionalData");
})
.ServerFiltering(true);
})
.AutoBind(false)
)
</div>
<div class='gewijzigdItem'>
<h4 class="gewijzigdDoor">Gewijzigd door:</h4>
#(Html.Kendo().ComboBox()
.Name("usersSetComboBox")
.DataTextField("DisplayName")
.DataValueField("UserName")
.Filter(FilterType.Contains)
.HtmlAttributes(new { #class = "comboStyle" })
.DataSource(source =>
{
source.Read(read =>
{
read.Action(MVC.BeheerTeksten.ActionNames.GebruikersIntoCombo_Read, MVC.BeheerTeksten.Name)
.Data("onAdditionalData");
})
.ServerFiltering(true);
})
.AutoBind(false)
)
</div>
<div class='vanItem'>
<h4 class="van">Van:</h4>
#(Html.Kendo().DateTimePicker()
.Name("vanTimepicker")
.Max(DateTime.Today)
.Events(events => events.Change("onVanTimeChange"))
.HtmlAttributes(new { #class = "dateTimePickerStyle;" })
)
</div>
<div class='totItem'>
<h4 class="tot">Tot:</h4>
#(Html.Kendo().DateTimePicker()
.Name("totTimepicker")
.Max(DateTime.Today)
.Events(events => events.Change("onTotTimeChange"))
.HtmlAttributes(new { #class = "dateTimePickerStyle;" })
)
</div>
</div>
</div>
<div class="separator"></div>
#*<hr />*#
<div class="zoekResultatLine">
<h2 class="zoekResultat">ZOEKRESULTAAT</h2>
</div>
#(Html.Kendo().Grid<TekstenViewModel.Tekst>()
.Name("Grid")
.Columns(columns =>
{
columns.Template(#<text></text>).ClientTemplate("<input type='checkbox'/>").Width(10).Hidden(!Model.Administrator);
columns.Bound(product => product.RESOURCE_SET_NAAM).Width(125).ClientTemplate("#= RESOURCE_SET_NAAM#");
columns.Bound(product => product.Naam).Width(125).ClientTemplate("#= Naam#");
columns.Bound(product => product.Waarde).Width(125).ClientTemplate("<div id='editorDiv'><div class='input'>#=Waarde#</div><div class='editor'>" +
Html.WebCore().LinkButton(type: ButtonType.MeerActies, htmlAttributes: new { onclick = "openPopupDemo('#: Waarde #', '#: ID #', 'Waarde')" }));
columns.Bound(product => product.Opmerking).Width(250).ClientTemplate("<div id='editorDiv'><div class='input'>#=Opmerking#</div><div class='editor'>" +
Html.WebCore().LinkButton(type: ButtonType.MeerActies, htmlAttributes: new { onclick = "openPopupDemo('#: Opmerking #', '#: ID #', 'Opmerking')" }));
columns.Template(#<text></text>).ClientTemplate("<div id='deleteDiv'><div class='delete'><a class=\"delete iconBtn\" onclick=\"deleteResourceItem(#: ID #, '#: Naam #')\"></a></div></div>").Width(10).Hidden(!Model.Administrator);
})
.Pageable()
.Sortable()
.Filterable()
.Events(events => events.Edit("onCellEdit").DataBinding("onDataBinding"))
.Groupable()
.Navigatable()
.Editable(editable => editable.Mode(GridEditMode.InCell).DisplayDeleteConfirmation(false))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.Events(e => e.Error("error_handler"))
.Model(model =>
{
model.Id(product => product.ID);
model.Field(product => product.Naam).Editable(Model.Administrator);
model.Field(product => product.Opmerking).Editable(Model.Administrator);
model.Field(product => product.Waarde).Editable(!Model.ReadOnly);
model.Field(product => product.RESOURCE_SET_ID).DefaultValue(Model.SetID);
model.Field(product => product.Type).DefaultValue(Domain.Agromilieu2.Common.Objects.Entities.Resources.ResourceType.GLOBAL_RESOURCES);
model.Field(product => product.Taal).DefaultValue(Domain.Agromilieu2.Common.Agromilieu2Constants.Resources.DEFAULT_TAAL_CODE);
})
.Create(create => create.Action(MVC.BeheerTeksten.ActionNames.ResourceItems_Create, MVC.BeheerTeksten.Name))
.Read(read => read.Action(MVC.BeheerTeksten.ActionNames.ResourceItems_Read, MVC.BeheerTeksten.Name, new { setID = Model.SetID }).Data("onReadAdditionalData"))
.Update(update => update.Action(MVC.BeheerTeksten.ActionNames.ResourceItems_Update, MVC.BeheerTeksten.Name))
.Destroy(destroy => destroy.Action(MVC.BeheerTeksten.ActionNames.ResourceItems_Delete, MVC.BeheerTeksten.Name))
)
)
#Html.WebCore().Popup.Remove("confirmResourceItemPopup", "Verwijderen resource item", "")
#section Scripts
{
#Scripts.Render(Links.Bundles.Scripts.BeheerTeksten.Teksten)
<script type="text/javascript">
function onCellEdit(e) {
var grid = $("#Grid").data("kendoGrid");
var row = $(e.container).closest("tr");
var colIdx = $("td", row).index($(e.container));
var columname = e.sender.columns[colIdx].field;
e.container.find("[name='" + columname + "']").toggleClass('editInput');
}
function onDataBinding(e) {
var grid = $("#Grid").data("kendoGrid");
if ($("#resourcesSetComboBox").data("kendoComboBox").value() == "")
grid.showColumn(1);
else
grid.hideColumn(1);
}
function onVanTimeChange() {
var vanTimeValue = kendo.toString($("#vanTimepicker").data("kendoDateTimePicker").value(), "dd/MM/yyyy HH:mm:ss.ffff")
$("#totTimepicker").data("kendoDateTimePicker").min(vanTimeValue);
}
function onTotTimeChange() {
var totTimeValue = kendo.toString($("#totTimepicker").data("kendoDateTimePicker").value(), "dd/MM/yyyy HH:mm:ss.ffff")
$("#vanTimepicker").data("kendoDateTimePicker").max(totTimeValue);
}
function onAdditionalData() {
var code = window.location.pathname.split('/');
return {
toepassingsCode: code[5]
};
}
function onReadAdditionalData() {
var resourceID = $.urlParam('setID');
if (resourceID) {
$("#resourcesSetComboBox").data("kendoComboBox").value(resourceID);
$("#resourcesSetComboBox").data("kendoComboBox").enable(false);
}
else
resourceID = $("#resourcesSetComboBox").data("kendoComboBox").value();
var user = $.urlParam('userName');
if (user) {
$("#usersSetComboBox").data("kendoComboBox").value(user);
$("#usersSetComboBox").data("kendoComboBox").enable(false);
}
else
user = $("#usersSetComboBox").data("kendoComboBox").value();
var vanTimeValue = $.urlParam('vanTime');
if (vanTimeValue) {
$("#vanTimepicker").data("kendoDateTimePicker").value(new Date(Date.parse(vanTimeValue, "dd/MM/yyyy HH:mm:ss")));
$("#vanTimepicker").data("kendoDateTimePicker").enable(false);
}
else
var vanTimeValue = kendo.toString($("#vanTimepicker").data("kendoDateTimePicker").value(), "dd/MM/yyyy HH:mm:ss.ffff")
var totTimeValue = $.urlParam('totTime');
if (totTimeValue) {
$("#totTimepicker").data("kendoDateTimePicker").value(totTimeValue);
$("#totTimepicker").data("kendoDateTimePicker").enable(false);
}
else
var totTimeValue = kendo.toString($("#totTimepicker").data("kendoDateTimePicker").value(), "dd/MM/yyyy HH:mm:ss.ffff")
return {
setID: resourceID,
userName: user,
vanTime: vanTimeValue,
totTime: totTimeValue
};
}
$.urlParam = function (name) {
var enc = decodeURI(window.location.href);
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(enc);
if (results != null)
return results[1];
}
function deleteResourceItem(resourceItemID, resourceItemName) {
domain.Agromilieu2.Wui.BeheerTeksten.Teksten.deleteResourceItem(resourceItemID, resourceItemName);
}
var selectedGridRowID = 0;
var selectedGridColumnName;
function openPopupDemo(gridCellContent, gridIdentifier, columnIdentifier) {
var editor = $("#waardeEditor").data("kendoEditor")
if (('#Html.Raw(Json.Encode(Model.ReadOnly))' == "false" && '#Html.Raw(Json.Encode(Model.Administrator))' == "false" && columnIdentifier != "Waarde") || '#Html.Raw(Json.Encode(Model.ReadOnly))' == "true")
editor.body.contentEditable = false;
else
editor.body.contentEditable = true;
editor.value(htmlDecode(gridCellContent));
domain.WebCore.popup.show("popupDemo");
selectedGridRowID = gridIdentifier;
selectedGridColumnName = columnIdentifier;
};
function htmlDecode(value) {
return $('<div/>').html(value).text();
}
function htmlEncode(value) {
return $('<div/>').text(value).html();
}
function htmlEscape(str) {
return String(str)
.replace(/"/g, '"')
.replace(/'/g, ''')
}
domain.WebCore.popup.configure("popupDemo")
.click(function (b) {
var grid = $("#Grid").data("kendoGrid");
var editor = $("#waardeEditor").data("kendoEditor")
var parentItem = grid.dataSource.get(selectedGridRowID);
parentItem.set(selectedGridColumnName, htmlEscape(htmlEncode(editor.value())));
});
function showAlertWindow(message) {
var alertWindow = $('#alertWindow').data('kendoWindow');
alertWindow.content(message);
alertWindow.refresh();
alertWindow.center();
alertWindow.open();
}
function error_handler(e) {
if (e.errors) {
var message = "";
$.each(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
showAlertWindow(message);
}
}
$(function () {
domain.Agromilieu2.Wui.BeheerTeksten.Teksten.init(
{
deleteResourceItemUrl: "#Url.Action(MVC.BeheerTeksten.ResourceItems_Delete())",
deleteResourceItemMessage: "<p>Bent u zeker dat u '{0}' wil verwijderen?</p><p><strong>Opgelet!</strong><br>Hierbij worden ook alle teksten verbonden aan deze resource set verwijderd.</p>",
ResourceItems_ReadUrl: "#Url.Action(MVC.BeheerTeksten.ResourceItems_Read())"
});
});
</script>
}
And here's my controller's code.
// GET /Agromilieu2/Beheer/Teksten/Teksten
[HttpGet]
[Domain.BasisArchitectuur.Framework.MVC.ActionFilters.MenuItem("Teksten")]
[IsAgromilieuActieAllowed(ActieClaims.TekstenRaadpleger)]
public virtual ActionResult Teksten(string toepassingsCode = null, long? setID = null, string taalCode = null, string resourceType = null, string user = null)
{
bool admin = SecurityHelper.IsActieAllowed(ActieClaims.TekstenAdmin);
LayoutService.SubTitle = DetailResources.TITEL_Header;
if (admin)
{
LayoutService.SubmitActions = new List<LinkButton>
{
new LinkButton { ButtonType = ButtonType.Toevoegen, CssClass = "myToevoegenButton", IsDisabled = setID == null, ClientId = "teste" },
new LinkButton { ButtonType = ButtonType.Delete, CssClass = "myVerwijderenButton" },
new LinkButton { ButtonType = ButtonType.Zoeken, CssClass = "primair myZoekenButton" }
};
}
else
{
LayoutService.SubmitActions = new List<LinkButton>
{
new LinkButton { ButtonType = ButtonType.Zoeken, CssClass = "primair myZoekenButton" }
};
}
if (string.IsNullOrEmpty(toepassingsCode))
{
return RedirectToAction(MVC.BeheerTeksten.Toepassingen());
}
else
{
if (!string.IsNullOrEmpty(resourceType) && resourceType == ResourceType.REFE_RESOURCES)
{
return RedirectToAction(MVC.BeheerTeksten.RefeTeksten(toepassingsCode, setID, taalCode));
}
else
{
if (string.IsNullOrEmpty(taalCode))
{
taalCode = Agromilieu2Constants.Resources.DEFAULT_TAAL_CODE;
}
LayoutService.SubTitle = string.Format("Beheer Teksten - {0}",
BL.Resources.Resources.GetToepassingen().First(x => x.Code == toepassingsCode).Omschrijving);
TekstenViewModel.Main model = new TekstenViewModel.Main
{
DefaultTaal = Agromilieu2Constants.Resources.DEFAULT_TAAL_CODE,
Filter = new TekstenViewModel.ZoekCriteria
{
ResourceSet_ID = setID,
Taal = taalCode,
userName = user
},
ToepassingsCode = toepassingsCode,
SetID = setID,
ReadOnly = !(SecurityHelper.IsActieAllowed(ActieClaims.TekstenAdmin) || SecurityHelper.IsActieAllowed(ActieClaims.TekstenBeheer)),
Administrator = SecurityHelper.IsActieAllowed(ActieClaims.TekstenAdmin)
};
return View(model);
}
}
}
[HttpPost]
[Domain.BasisArchitectuur.Framework.MVC.ActionFilters.MenuItem("Teksten")]
[IsAgromilieuActieAllowed(ActieClaims.TekstenRaadpleger)]
public virtual ActionResult ResourceItems_Read([DataSourceRequest]DataSourceRequest request, long? setID, string userName, string vanTime, string totTime, string taalCode = Agromilieu2Constants.Resources.DEFAULT_TAAL_CODE)
{
DateTime? newVanTime = null;
DateTime? newTotTime = null;
if(!String.IsNullOrEmpty(vanTime))
newVanTime = DateTime.Parse(vanTime);
if (!String.IsNullOrEmpty(totTime))
newTotTime = DateTime.Parse(totTime);
TekstenViewModel.ZoekCriteria searchCriteria = new TekstenViewModel.ZoekCriteria
{
ResourceSet_ID = setID,
type_Code = ResourceType.GLOBAL_RESOURCES,
Taal = taalCode,
userName = userName,
vanTime = newVanTime,
totTime = newTotTime
};
List<TekstenViewModel.Tekst> resourceItemsList = new List<Models.BeheerTeksten.TekstenViewModel.Tekst>();
resourceItemsList = GetResourceItemsList(searchCriteria);
return Json(resourceItemsList.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
[AcceptVerbs(HttpVerbs.Post)]
[Domain.BasisArchitectuur.Framework.MVC.ActionFilters.MenuItem("Teksten")]
[IsAgromilieuActieAllowed(ActieClaims.TekstenBeheren)]
public virtual ActionResult ResourceItems_Create([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<TekstenViewModel.Tekst> resourceItems)
{
List<ResourceItemDto> entities = new List<ResourceItemDto>();
if (ModelState.IsValid)
{
try
{
using (IProxy<IResourceService> proxy = _proxyFactory.Create<IResourceService>())
{
foreach (TekstenViewModel.Tekst tekstenViewModel in resourceItems)
{
ResourceItemDto resourceItem = new ResourceItemDto
{
ResourceItem_ID = tekstenViewModel.ID,
ResourceSet_ID = tekstenViewModel.RESOURCE_SET_ID,
Naam = HttpUtility.HtmlDecode(tekstenViewModel.Naam),
Opmerking = HttpUtility.HtmlDecode(tekstenViewModel.Opmerking),
Waarde = HttpUtility.HtmlDecode(tekstenViewModel.Waarde),
Type_Code = tekstenViewModel.Type,
Taal_Code = tekstenViewModel.Taal,
ResourceWaarde_ID = tekstenViewModel.WAARDE_ID
};
entities.Add(resourceItem);
}
proxy.Client.CheckIfNameExists(entities);
proxy.Client.AddOrUpdateResourceItem(entities.AsEnumerable());
}
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
}
else
{
var errMsg = ModelState.Values
.Where(x => x.Errors.Count >= 1)
.Aggregate("Model State Errors: ", (current, err) => current + err.Errors.Select(x => x.ErrorMessage));
ModelState.AddModelError(string.Empty, errMsg);
}
//ModelState.AddModelError("Naam", );
//resourceItems = GetResourceItemsList(new TekstenViewModel.ZoekCriteria { Taal = resourceItems.FirstOrDefault().Taal, ResourceSet_ID = resourceItems.FirstOrDefault().RESOURCE_SET_ID });
return Json(entities.ToDataSourceResult(request, ModelState));
}
[AcceptVerbs(HttpVerbs.Post)]
[Domain.BasisArchitectuur.Framework.MVC.ActionFilters.MenuItem("Teksten")]
[IsAgromilieuActieAllowed(ActieClaims.TekstenBeheren)]
public virtual ActionResult ResourceItems_Update([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<TekstenViewModel.Tekst> resourceItems)
{
List<ResourceItemDto> entities = new List<ResourceItemDto>();
if (ModelState.IsValid)
{
try
{
using (IProxy<IResourceService> proxy = _proxyFactory.Create<IResourceService>())
{
foreach (TekstenViewModel.Tekst tekstenViewModel in resourceItems)
{
ResourceItemDto resourceItem = new ResourceItemDto
{
ResourceItem_ID = tekstenViewModel.ID,
ResourceSet_ID = tekstenViewModel.RESOURCE_SET_ID,
Naam = HttpUtility.HtmlDecode(tekstenViewModel.Naam),
Opmerking = HttpUtility.HtmlDecode(tekstenViewModel.Opmerking),
Waarde = HttpUtility.HtmlDecode(tekstenViewModel.Waarde),
Type_Code = tekstenViewModel.Type,
Taal_Code = tekstenViewModel.Taal,
ResourceWaarde_ID = tekstenViewModel.WAARDE_ID
};
entities.Add(resourceItem);
}
proxy.Client.AddOrUpdateResourceItem(entities.AsEnumerable());
}
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
}
else
{
var errMsg = ModelState.Values
.Where(x => x.Errors.Count >= 1)
.Aggregate("Model State Errors: ", (current, err) => current + err.Errors.Select(x => x.ErrorMessage));
ModelState.AddModelError(string.Empty, errMsg);
}
return Json(resourceItems.ToDataSourceResult(request, ModelState));
}
[HttpDelete]
[IsAgromilieuActieAllowed(ActieClaims.TekstenBeheren)]
public virtual ActionResult ResourceItems_Delete(long? id)
{
using (IProxy<IResourceService> proxy = _proxyFactory.Create<IResourceService>())
{
proxy.Client.DeleteResourceItemRecursively(id);
}
return Content(CoreService.LastMainScreenUrl ?? MvcConfig.DefaultStartupUrl);
}
[HttpPost]
[IsAgromilieuActieAllowed(ActieClaims.TekstenBeheren)]
public virtual ActionResult ResourceItems_Delete( [Bind(Prefix="models")] List<TekstenViewModel.Tekst> resourceItems)
{
using (IProxy<IResourceService> proxy = _proxyFactory.Create<IResourceService>())
{
foreach(TekstenViewModel.Tekst resourceItem in resourceItems )
{
proxy.Client.DeleteResourceItemRecursively(resourceItem.ID);
}
}
return Content(CoreService.LastMainScreenUrl ?? MvcConfig.DefaultStartupUrl);
}
[HttpGet]
[IsAgromilieuActieAllowed(ActieClaims.TekstenRaadpleger)]
public virtual JsonResult ResourceSetsIntoCombo_Read(string toepassingsCode)
{
ResourceWcfDataServiceProxy proxy = DependencyResolver.Current.GetService<ResourceWcfDataServiceProxy>();
IEnumerable<ResourceSetsViewModel.ResourceSet> sets =
Enumerable.Repeat(new ResourceSetsViewModel.ResourceSet { Naam = "Maak een selectie" }, 1).Union(proxy.ResourceSetSet
.Where(s => s.ToepassingsCode == toepassingsCode)
.Select(s => new
{
ID = s.ID,
Naam = s.Naam,
Opmerking = s.Opmerking,
Type = s.Type.Code
}).ToList()
.Select(s => new ResourceSetsViewModel.ResourceSet
{
ID = s.ID,
Naam = s.Naam,
Opmerking = s.Opmerking,
Type = s.Type
}));
return Json(sets.ToList(), JsonRequestBehavior.AllowGet);
}
[HttpGet]
[IsAgromilieuActieAllowed(ActieClaims.TekstenRaadpleger)]
public virtual JsonResult GebruikersIntoCombo_Read(string toepassingsCode)
{
IEnumerable<TekstenViewModel.UserInfo> journalingUsers;
using (IProxy<IResourceService> proxy = _proxyFactory.Create<IResourceService>())
{
journalingUsers = Enumerable.Repeat(new TekstenViewModel.UserInfo { UserName = null, DisplayName = "Maak een selectie" }, 1)
.Union(proxy.Client.GetUsers(toepassingsCode).Select(x => new TekstenViewModel.UserInfo { UserName = x, DisplayName = x }));
}
return Json(journalingUsers.ToList(), JsonRequestBehavior.AllowGet);
}
When I update, read or delete, everything works fine. When I create, it's like I'm not getting back the right data in the grid.
I mean, I create a new record and press Save, it calls the savechanges event of the grid. So far so good, but if I press Save again, it calls the savechanges event again and I get this error.
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
Here's a picture of the grid before creating a new record.
Here's a picture of the grid after inserting a new record
The first record should be the last. Have no idea why this is happening.