PDA

View Full Version : [CLOSED] combo remote validation has invalid json error



susanz
Jan 30, 2015, 7:30 PM
I have dynamic grid and a combo column needs remote direct validation. when combo is selected, the busy icon shows, but not seeing network call to the direct method and console has error:

Uncaught Ext.JSON.decode(): You're trying to decode an invalid JSON String: App.direct.ValidateCombo
3ext.axd?v=1895:18 Uncaught Ext.JSON.decode(): You're trying to decode an invalid JSON String: App.direct.ValidateComboext.axd?v=1895:18 Ext.Error.Ext.extend.statics.raiseext.axd?v=1895:1 8 Ext.JSON.me.decodeext.axd?v=1895:475 Ext.form.field.Base.override.remoteValidateext.axd ?v=1895:18 c

Not sure what I did wrong? I am using ext.net 2.5
Thanks

index.cshtml:


@using Ext.Net;
@using Ext.Net.MVC;

@model EXTNETTEst30.ViewModels.GridViewModel

@{
Layout = null;
}

<!DOCTYPE html>

<html>
<head>
<title>Ext.NET MVC Sample</title>

<link type="text/css" rel="stylesheet" href="http://speed.ext.net/www/intro/css/main.css" />
</head>
<body>
@(Html.X().ResourceManager())

<header>
<a href="http://ext.net/"><img src="http://speed.ext.net/identity/extnet-logo-white-large.png" class="logo"/></a>
</header>


@(
Html.X().GridPanel()
.Frame(true)
.Height(800)
.Width(600)
.Store(
Html.X().Store()
.RemotePaging(false)
.PageSize(20)
.Proxy (
Html.X().AjaxProxy ()
.Url (Url.Action("LoadGridData", "ExtNet"))
.Reader(Html.X().JsonReader().Root("data").MessageProperty("message"))
)
.Model(Model.StoreModel) //define model data schema
.Parameters( new { gridId = Model.GridIDInt })

)
.ColumnModel(Model.Columns) //define display columns
.ColumnModel (
Html.X().CommandColumn()
.Width(70)
)
.View(
Html.X().GridView()
.StripeRows(true)
.LoadingText("Loading Grid Data...")
//.GetRowClass ( new Action<JFunction>("getRowClass"))
)
.Plugins(
Html.X().RowEditing()//.CellEditing().ClicksToEdit(1)
)
.Listeners(ls =>
{
ls.ValidateEdit.Fn = "validateEditor"; // this works
})
.TopBar(
Html.X().Toolbar()
.AutoScroll(true)
.Items(
Html.X().Button().ID("AddBtn")
.Text("Add")
// .Handler("onAddRow (this.up('grid'))")
)
)

)

<script>
Ext.create('Scripts.VTypes').init();


var validateEditor = function (editor, e) {

var column = e.column;

if (column != null) {
var valid = column.field.isValid();

if (!valid) {
e.cancel = true;
}
}

}

</script>


</body>
</html>

//ExtNetControl.cs:

using System;
using System.Web.Mvc;
using System.Collections.Generic;
using Ext.Net;
using Ext.Net.MVC;
using EXTNETTEst30.ViewModels;
using Newtonsoft.Json;


namespace EXTNETTEst30.Controllers
{
public class ExtNetController : Controller
{
public ActionResult Index()
{
// set view model with store schema definition and display column definitions
var vm = new GridViewModel();

vm.StoreModel = BuildStoreModel();

vm.Columns = BuildEditableColumn(vm.StoreModel.Fields);

return this.View(vm);
}

public Model BuildStoreModel()
{
Model storeModel = new Model();

storeModel.Fields.Add(new ModelField("Combo"));

return storeModel;
}

public IEnumerable<ColumnBase> BuildEditableColumn(ModelFieldCollection mfc)
{

ItemsCollection<ColumnBase> colCollection = new ItemsCollection<ColumnBase>();

Column col;

foreach (var mf in mfc)
{
col = new Column();

col.Text = mf.Name;
col.DataIndex = mf.Name;
ComboBox cob = new ComboBox();
cob.AllowBlank = false;
cob.QueryMode = DataLoadMode.Local;
cob.ForceSelection = true;
cob.DisplayField = "Text";
cob.ValueField = "Value";
cob.EmptyText = "Select a One...";
cob.IsRemoteValidation = true;
cob.RemoteValidation.DirectFn = "App.direct.ValidateCombo";
cob.RemoteValidation.ErrorMessage = "Wrong item!";
//cob.RemoteValidation.Validation += ValidateCombo; //.Url = Url.Action("ValidateCombo", "ExtNet");
//cob.RemoteValidation.ValidationEvent = "select";
//cob.RemoteValidation.EventOwner = ValidationEventOwner.Field;

var proxy = new AjaxProxy();
proxy.Url = Url.Action("LoadCombo", "ExtNet");
proxy.Reader.Add(new Ext.Net.JsonReader { Root = "data" });
var model = new Model { IDProperty = "Value" };
model.Proxy.Add(proxy);
model.Fields.Add(new ModelField { Name = "Text" });
model.Fields.Add(new ModelField { Name = "Value" });
var store = new Store { AutoLoad = true };
store.Model.Add(model);
cob.Store.Add(store);
cob.TypeAhead = true;

col.Editor.Add(cob);
colCollection.Add(col);

}

return colCollection;


}
[DirectMethod]
public object ValidateCombo(string value) //(object sender, RemoteValidationEventArgs e)
{

if (value == "Item2")
return true;

return "Item2 is valid value only";

}

public ActionResult LoadGridData(string action, Dictionary<string, object> extraParams, int gridId)
{
var l = new List<Dictionary<string, object>>();
var row = new Dictionary<string, Object>();

row.Add("Combo", "Item1");
l.Add(row);


return this.Store(l);
}

public ActionResult LoadCombo()
{
var results = new List<NewListItem>();
results.Add(new NewListItem { Text = "Item1", Value = "Item1" });
results.Add(new NewListItem { Text = "Item2", Value = "Item2" });

return this.Store(results);

}



}
}

GridViewModel.cs:

public class GridViewModel
{

public Model StoreModel { get; set; }
public IEnumerable<ColumnBase> Columns { get; set; }

}

fabricio.murta
Feb 01, 2015, 5:36 PM
Hello, I couldn't run your sample out-of-the-box. There are several missing actions and classes. I tried to stub some of them but it was becoming too much and I might miss the point you wanted me to help you fix.

So, I'll try my best guess based on the code I can read. It might not be very helpful though.

In general, you can't just return anything from a DirectMethod. If you need to return arbitrary data, you can make your directMethod interact with a containter/store into your page.

In your case of remote validation though, I believe all you need to return is false/true, and maybe provide an error message depending on the error found. For which case, you may easily translate the behavior of the following WebForms example to your scenario, using MVC: Remote validation form (http://examples2.ext.net/#/Form/Validation/Remote_Validation/)

If I could understand well your problem, you should make your directMethod signature exactly as the sample above. Then, instead of returning a string, you should do as the sample: provide feedback by assigning true/false to e.Success and, optionally, an error message into e.ErrorMessage.

Well, I really hope I could help you with this. If not, please provide a working, minimal, sample code that reproduces your issue there. You might want to fill the grid with a constant array, for example.

susanz
Feb 01, 2015, 11:16 PM
Hi fabricio.murta, Thanks for your information. I think my issue is the direct method some how is not recognized by the app. I changed to use url and it works. but I still want to know in, MVC how should I define the directFn. I decorated the method with [DirectMethod], do I need to decorate the control class ? how should I define the area name ?

The remote validation method worked with url action. but the return does not integrated with grid row editor. the Update button and Error list does not act right based on the validation returns. When the combo shows no err, the Update is disabled, when combo shows error, the Update button is enabled. How should I make row edit work with remove validation?




public JsonResult ValidateCombo(string value)
{
// Even ids are valid
bool success = value == "Item2";
return new JsonResult
{
Data = new
{
valid = success,
message = success ? null : "Invalid item",
}
};
}

//How the combo if configured now:

public IEnumerable<ColumnBase> BuildEditableColumn(ModelFieldCollection mfc)
{

ItemsCollection<ColumnBase> colCollection = new ItemsCollection<ColumnBase>();

Column col;

foreach (var mf in mfc)
{
ComboBox cob = new ComboBox();
cob.ID = "testComboBox";
cob.AllowBlank = false;
cob.QueryMode = DataLoadMode.Local;
cob.ForceSelection = true;
cob.DisplayField = "Text";
cob.ValueField = "Value";
cob.EmptyText = "Select a One...";
cob.IsRemoteValidation = true;
cob.RemoteValidation.Url = Url.Action("ValidateCombo");//.DirectFn = "App.direct.ValidateCombo";
cob.RemoteValidation.Json = true;
cob.RemoteValidation.EventOwner = ValidationEventOwner.Field;
cob.RemoteValidation.DisableCaching = true;
cob.RemoteValidation.CleanRequest = true;
cob.RemoteValidation.Method = HttpMethod.POST;
cob.RemoteValidation.ValidationEvent = "select";

var proxy = new AjaxProxy();
proxy.Url = Url.Action("LoadCombo", "ExtNet");
proxy.Reader.Add(new Ext.Net.JsonReader { Root = "data" });
var model = new Model { IDProperty = "Value" };
model.Proxy.Add(proxy);
model.Fields.Add(new ModelField { Name = "Text" });
model.Fields.Add(new ModelField { Name = "Value" });
var store = new Store { AutoLoad = true };
store.Model.Add(model);
cob.Store.Add(store);
cob.TypeAhead = true;

col.Editor.Add(cob);

colCollection.Add(col);

}

return colCollection;


}

fabricio.murta
Feb 06, 2015, 8:10 PM
Hello @susanz,

All I could do with your code update is see that you're trying to use the col variable without instantiating it before. I couldn't make the code run. It is missing some definitions I would need in order to have it working.

Please, can you provide an working, minimal sample for your view+controller+model, emphasizing the problem with the validation? Else, I am afraid I will not be able to help you point what you could do to validate the way you want.

The Forum Guidelines For Posting New Topics (http://forums.ext.net/showthread.php?3440) should help you with coming up with that sample.

susanz
Feb 06, 2015, 8:22 PM
You can close this for now. I have other issue to work on and I may not need to use remove validator. I'll create new ticket with demo code if I need.
Thanks
-szhang