Bind problem using JSONP and KendoUI ListView

6 posts, 0 answers
  1. Søren Hartig
    Søren Hartig avatar
    24 posts
    Member since:
    Apr 2008

    Posted 06 Dec 2012 Link to this post

    Hello there,

    I'm getting pretty frustrated. I have been trying to get my RESTful WCF service to work with the ListView controller. I was reusing the code from the demo (http://demos.kendoui.com/web/listview/editing.html) and adjusting it to my own needs. I have googled for help on how to enable my service to support JSONP, even though in my test bench I execute it locally.

    I have a webservice that produces this JSON output:
    [{"Id":"acd34cd2-4500-4e2e-988d-2f71738cb7b6","Name":"Plan 1","NextRun":"06-01-2013 04:43:55","NoOfJobs":7,"Status":0},{"Id":"5431e4ef-943c-4bcb-b747-378416face14","Name":"Plan 2","NextRun":"13-04-2013 03:23:02","NoOfJobs":7,"Status":0},{"Id":"ab9ce9ea-c9d1-4f90-be36-b6aca23c247d","Name":"Plan 3","NextRun":"09-12-2012 13:11:04","NoOfJobs":7,"Status":0},{"Id":"93b4689b-d39c-45fa-979a-93148dd81978","Name":"Plan 4","NextRun":"05-01-2013 18:56:21","NoOfJobs":7,"Status":0},{"Id":"61e89143-e6d6-4d3b-9c06-88509c2c9b55","Name":"Plan 5","NextRun":"06-03-2013 03:03:07","NoOfJobs":7,"Status":0},{"Id":"877244ee-3a63-4733-8f3e-a8154ab5b04c","Name":"Plan 6","NextRun":"05-02-2013 00:17:46","NoOfJobs":7,"Status":0}]

    The webservice looks like this:
    [ServiceContract]
        public interface IPlanListRESTService
        {
            [OperationContract]
            [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "fillplanlist/{count}")]
            List<Plan> FillPlanList(string count);

            [OperationContract]
            [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "plan")]
            bool AddPlan(Plan plan);

            [OperationContract]
            [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "planlist")]
            List<Plan> GetPlanList();

            [OperationContract]
            [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "xml/{id}")]
            string XMLData(string id);

            [OperationContract]
            [WebInvoke(Method   = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "json/{id}")]
            string JSONData(string id);
        }

        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        public class PlanListRESTService : IPlanListRESTService
        {

            List<Plan> planList = new List<Plan>();
            static Random rand = new Random();

            public List<Plan> FillPlanList(string count)
            {
                try
                {
                    int noOfPlans= Convert.ToInt32(count);

                    if ((noOfPlans < 0) || (noOfPlans > 25))
                        return planList;

                    planList.Clear();

                    for (int i = 1; i <= noOfPlans; i++)
                    {
                        Plan plan = new Plan();

                        plan.Id = Guid.NewGuid().ToString();
                        plan.Name = "Plan " + i.ToString();
                        plan.Status = PlanStatus.Waiting;

                        Random random = new Random();
                        plan.NoOfJobs = random.Next(0, 8);

                        plan.NextRun = GetRandomDate(new DateTime(2012, 11, 1), new DateTime(2013, 5, 1));

                        planList.Add(plan);
                    }

                    return planList;
                }
                catch (Exception)
                {
                    return planList;
                }
            }

            public bool AddPlan(Plan plan)
            {
                plan.Id = Guid.NewGuid().ToString();
                planList.Add(plan);

                return true;
            }

            public List<Plan> GetPlanList()
            {
                return planList;
            }

            public string XMLData(string id)
            {
                return "You requested product " + id;
            }

            public string JSONData(string id)
            {
                return "You requested product " + id;
            }

            public string ToJSon(object obj)
            {
                JavaScriptSerializer oSerializer = new JavaScriptSerializer();
                return oSerializer.Serialize(obj);
            }

            public string GetRandomDate(DateTime dtStart, DateTime dtEnd)
            {
                int cdayRange = (dtEnd - dtStart).Days;

                return dtStart.AddDays(rand.NextDouble() * cdayRange).ToString();
            }
        }

    The web.config for the service looks like this:
    <?xml version="1.0"?>
    <configuration>

      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5"/>
      </system.web>
      <system.serviceModel>
        <services>
          <service name="PlanListRESTService.PlanListRESTService" behaviorConfiguration="ServiceBehavior">
            <endpoint address="" binding="webHttpBinding"
                      bindingConfiguration="webHttpBindingWithJsonP"
                      contract="PlanListRESTService.IPlanListRESTService"
                      behaviorConfiguration="Web"/>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceBehavior">
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
          </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="Web">
              <webHttp/>
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <bindings>
          <webHttpBinding>
            <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" />
          </webHttpBinding>
        </bindings>
        <protocolMapping>
            <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>    
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
        <!--
            To browse web app root directory during debugging, set the value below to true.
            Set to false before deployment to avoid disclosing web app folder information.
          -->
        <directoryBrowse enabled="true"/>
      </system.webServer>

    </configuration>

    And finally here is the Index.cshtml file that should render the listview with my data, but it doesn't :-( :
    @{
        ViewBag.Title = "Home Page";
    }

    <h2>@ViewBag.Message</h2>
    <div id="example" class="k-content">
        <div class="k-toolbar k-grid-toolbar">
            <a class="k-button k-button-icontext k-add-button" href="#"><span class="k-icon k-add"></span>Add new plan</a>
        </div>
        <div id="listView"></div>

        <div id="pager" class="k-pager-wrap">
        </div>

        <script type="text/x-kendo-tmpl" id="template">
            <div class="plan-view">
                <dl>
                    <dt>Name</dt>
                    <dd>${Name}</dd>
                    <dt>No. of jobs</dt>
                    <dd>${NoOfJobs}</dd>
                    <dt>Next run:</dt>
                    <dd>${NextRun}</dd>
                    <dt>Status</dt>
                    <dd>${Status}</dd>
                </dl>
                <div class="edit-buttons">
                    <a class="k-button k-button-icontext k-edit-button" href="\\#"><span class="k-icon k-edit"></span>Edit</a>
                    <a class="k-button k-button-icontext k-delete-button" href="\\#"><span class="k-icon k-delete"></span>Delete</a>
                </div>
            </div>
        </script>

        <script type="text/x-kendo-tmpl" id="editTemplate">
            <div class="plan-view">
                <dl>
                    <dt>Plan Name</dt>
                    <dd>
                        <input type="text" data-bind="value:Name" name="Name" required="required" validationMessage="required" />
                        <span data-for="Name" class="k-invalid-msg"></span>
                    </dd>
                    <dt>No. of jobs</dt>
                    <dd>
                        <input type="text" data-bind="value:NoOfJobs" data-role="numerictextbox" data-type="number" name="NoOfJobs" required="required" min="0" validationMessage="required" />
                        <span data-for="NoOfJobs" class="k-invalid-msg"></span>
                    </dd>
                    <dt>Status</dt>
                    <dd>
                        <input type="text" data-bind="value:Status" name="Status" required="required" data-type="number" min="0" validationMessage="required" />
                        <span data-for="Status" class="k-invalid-msg"></span>
                    </dd>
                    <dt>Next run</dt>
                    <dd>
                        <input type="text" data-bind="value:NextRun" name="NextRun" required="required" data-type="number" min="0" validationMessage="required" />
                        <span data-for="NextRun" class="k-invalid-msg"></span>
                    </dd>
                </dl>
                <div class="edit-buttons">
                    <a class="k-button k-button-icontext k-update-button" href="\\#"><span class="k-icon k-update"></span>Save</a>
                    <a class="k-button k-button-icontext k-cancel-button" href="\\#"><span class="k-icon k-cancel"></span>Cancel</a>
                </div>
            </div>
        </script>

        <script>
            $(document).ready(function () {
                var crudServiceBaseUrl = "http://localhost:8080/PlanListRESTService",
                    dataSource = new kendo.data.DataSource({
                        transport: {
                            read:  {
                                url: crudServiceBaseUrl + "/fillplanlist/20",
                                dataType: "jsonp"
                            },
                            //update: {
                            //    url: crudServiceBaseUrl + "/fillplanlist/20",
                            //    dataType: "jsonp"
                            //},
                            //destroy: {
                            //    url: crudServiceBaseUrl + "/fillplanlist/20",
                            //    dataType: "jsonp"
                            //},
                            //create: {
                            //    url: crudServiceBaseUrl + "/fillplanlist/20",
                            //    dataType: "jsonp"
                            //},
                            parameterMap: function(options, operation) {
                                if (operation !== "read" && options.models) {
                                    return {models: kendo.stringify(options.models)};
                                }
                            }
                        },
                        batch: true,
                        pageSize: 6,
                        schema: {
                            model: {
                                id: "Id",
                                fields: {
                                    Id: { editable: false, nullable: true },
                                    Name: "Name",
                                    NextRun: "Next run",
                                    NoOfJobs: { type: "number" },
                                    Status: { type: "number" }
                        }
                            }
                        }
                    });


                $("#pager").kendoPager({
                    dataSource: dataSource
                });

                var listView = $("#listView").kendoListView({
                    dataSource: dataSource,
                    template: kendo.template($("#template").html()),
                    editTemplate: kendo.template($("#editTemplate").html())
                }).data("kendoListView");

                $(".k-add-button").click(function(e) {
                    listView.add();
                    e.preventDefault();
                });
            });
        </script>
        <style scoped>
            .plan-view
            {
                float: left;
                width: 300px;
                margin: 5px;
                padding: 3px;
                -moz-box-shadow: inset 0 0 50px rgba(0,0,0,0.1);
                -webkit-box-shadow: inset 0 0 50px rgba(0,0,0,0.1);
                box-shadow: inset 0 0 50px rgba(0,0,0,0.1);
                border-top: 1px solid rgba(0,0,0,0.1);
                -webkit-border-radius: 8px;
                -moz-border-radius: 8px;
                border-radius: 8px;
            }

            .plan-view dl
            {
                margin: 10px 0;
                padding: 0;
                min-width: 0;
            }
            .plan-view dt, dd
            {
                float: left;
                margin: 0;
                padding: 0;
                height: 30px;
                line-height: 30px;
            }
            .plan-view dt
            {
                clear: left;
                padding: 0 5px 0 15px;
                text-align: right;
                opacity: 0.6;
                width: 100px;
            }
            .k-listview
            {
                border: 0;
                padding: 0;
                min-width: 0;
            }
            .k-listview:after, .plan-view dl:after
            {
                content: ".";
                display: block;
                height: 0;
                clear: both;
                visibility: hidden;
            }
            .edit-buttons
            {
                text-align: right;
                padding: 5px;
                min-width: 100px;
                border-top: 1px solid rgba(0,0,0,0.1);
                -webkit-border-radius: 8px;
                -moz-border-radius: 8px;
                border-radius: 8px;
            }

            .k-toolbar, #listView, .k-pager-wrap
            {
                width: 960px;
                /*margin: 0 auto;*/
                -webkit-border-radius: 11px;
                -moz-border-radius: 11px;
                border-radius: 11px;
            }
            #listView
            {
                width: 960px;
            }
            span.k-invalid-msg
            {
                position: absolute;
                margin-left: 160px;
                margin-top: -26px;
            }
        </style>
    </div>

    <p>
        To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
    </p>

    <p>
        To learn more about working with the Kendo UI Complete for ASP.NET MVC, you can visit the folowing resources:
    </p>
    <ul>
            <li><a href="http://demos.kendoui.com/">online demos</a></li>
            <li><a href="http://docs.kendoui.com/getting-started/using-kendo-with/aspnet-mvc/introduction">online documentation</a></li>
            <li><a href="http://www.kendoui.com/forums.aspx">community forums</a></li>
            <li><a href="http://tv.telerik.com/search?FilterByTags=KendoUI">videos on Telerik TV</a></li>
    </ul>

    Help me please
  2. Søren Hartig
    Søren Hartig avatar
    24 posts
    Member since:
    Apr 2008

    Posted 10 Dec 2012 Link to this post

    Anyone, I'm really stuck here :-(
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Daniel
    Admin
    Daniel avatar
    2117 posts

    Posted 10 Dec 2012 Link to this post

    Hello,

    The code looks correct. Are there any JavaScript errors thrown? What is the response from the server when JSONP is enabled? It would be helpful if you could send a sample project so I can investigate what exactly is going wrong.

    Kind regards,
    Daniel
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  5. Søren Hartig
    Søren Hartig avatar
    24 posts
    Member since:
    Apr 2008

    Posted 11 Dec 2012 Link to this post

    Hi Daniel.

    Thank you for your answer. It is impossible for me to attach a sample solution at the size of 2MB or smaller.
    Which part of my solution do you want ? You can see the code for my RESTful service, the web.config.
    I host the service from a windows service via the OnStart and OnStop events. The web application is a KendoUI
    MVC 4 project with modified source code from the demo (as I mentioned before).

    Thanks in advance...

  6. Søren Hartig
    Søren Hartig avatar
    24 posts
    Member since:
    Apr 2008

    Posted 13 Dec 2012 Link to this post

    Hi Daniel,

    I have compressed my VS 2012 solution to approx. 14 MB. That is the best I can do.
    Is there a mail-address I can mail it to ? 

    I'm about to ditch the whole KendoUI thing, but I'm giving it a last go.

    I would really like you to take a look at it before I find an alternative solution.

  7. Daniel
    Admin
    Daniel avatar
    2117 posts

    Posted 13 Dec 2012 Link to this post

    Hi again,

    The service response should indicate whether the callback was added or not. As I mentioned in my previous reply the code looks correct. I am attaching a sample project with similar setup which seems to work correctly on my side. Let me know if it works on yours.

    Regards,
    Daniel
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
Back to Top
UI for ASP.NET MVC is VS 2017 Ready