Cannot populate Scheduler with WCF Web Service

2 posts, 0 answers
  1. myobis
    myobis avatar
    6 posts
    Member since:
    Apr 2008

    Posted 14 Feb 2011 Link to this post

    Hello,

    we are using the RadScheduler for quite some time in our Application. So far the data access had been done with Entity Framework 4. In the Load event we assigned an IQueryable<MyAppointment> to thr Scheduler.DataSource. This is straight forward and works just fine. Only problem is that due to any appointments of our clients, the Scheduler is very slow.
    To solve that problem we want to populate our scheduler with Wcf Web Service. I don't know if I am missing something, but it doesn't seem to work. I used you many samples and here is what I did. Please tell me if something is wrong:

    The implementation of the abstract class "DbSchedulerProviderBase":
    I use a a static Business Class to get the Appointments and do CRUD operations. In your examples I saw that you are using direct db connections. Is my approach wrong? Also since I am not using any resources the GetResources-Method returns null.
    namespace myOBIS_Entities.SchedulerProvider
    {
        public class MyobisSchedulerProvider : DbSchedulerProviderBase
        {
            public override IEnumerable<Appointment> GetAppointments(ISchedulerInfo schedulerInfo)
            {
                IQueryable<myOBIS_Entities.EntityFramework.Appointment> MyoAppointments = CallingEnvironment.Membership.CurrentOrganisation.Appointments;
                List<Appointment> appointments = new List<Appointment>();
      
                foreach (myOBIS_Entities.EntityFramework.Appointment myoApp in MyoAppointments)
                {
                    Appointment apt = new Appointment();
                    apt.ID = myoApp.AppointmentId;
                    apt.Subject = myoApp.Subject;
                    apt.Start = myoApp.AppointmentStart;
                    apt.End = myoApp.AppointmentEnd;
                    apt.DataItem = myoApp;
                    apt.ToolTip = "Appointment From WebService";
                    appointments.Add(apt);
                }
      
                return appointments.AsEnumerable();
            }
      
            public override void Update(ISchedulerInfo schedulerInfo, Appointment appointmentToUpdate)
            {
                var myoSchedulerInfo = schedulerInfo as MyobisSchedulerInfo;
                AppointmentController.EditAppointment(
                    Guid.Parse(appointmentToUpdate.ID.ToString()),
                    myoSchedulerInfo.MaxAttendees,
                    myoSchedulerInfo.Price,
                    myoSchedulerInfo.LastMinutePrice,
                    myoSchedulerInfo.DaysBeforeLastMinute);
            }
      
            public override IDictionary<ResourceType, IEnumerable<Resource>> GetResources(ISchedulerInfo schedulerInfo)
            {
                return null;       
              
            }
      
            public override void Insert(ISchedulerInfo schedulerInfo, Appointment appointmentToInsert)
            {
                var myoSchedulerInfo = schedulerInfo as MyobisSchedulerInfo;
      
                AppointmentController.InsertAppointment(
                   myoSchedulerInfo.OrganisationId,
                   myoSchedulerInfo.EventProductId,
                   myoSchedulerInfo.LocationId,
                   myoSchedulerInfo.Type,
                   appointmentToInsert.Start,
                   appointmentToInsert.End,
                   myoSchedulerInfo.MaxAttendees,
                   myoSchedulerInfo.CurrencyCode,
                   myoSchedulerInfo.Price,
                   myoSchedulerInfo.LastMinutePrice,
                   myoSchedulerInfo.DaysBeforeLastMinute);
            }
      
            public override void Delete(ISchedulerInfo schedulerInfo, Appointment appointmentToDelete)
            {
                AppointmentController.DeleteAppointment(Guid.Parse(appointmentToDelete.ID.ToString()));
            }
        }
    }

    Next I implement the ISchedulerInfo interface by derivating form the SchedulerInfo class:
    Here I need additional Info for my own Appointment objects.
    namespace myOBIS_Entities.SchedulerProvider
    {
        public class MyobisSchedulerInfo : SchedulerInfo 
        {
            public Guid OrganisationId { get; set; }
            public Guid EventProductId { get; set; }
            public Guid LocationId { get; set; }
            public int Type { get; set; }
            public short MaxAttendees { get; set; }
            public string CurrencyCode { get; set; }
            public double Price { get; set; }
            public double LastMinutePrice { get; set; }
            public int DaysBeforeLastMinute { get; set; }
      
            public MyobisSchedulerInfo() { }
      
            public MyobisSchedulerInfo(
                ISchedulerInfo baseInfo,
                Guid orgId,
                Guid eventProductId,
                Guid locationId,
                int type,
                short maxAttendees,
                string currencyCode,
                double price,
                double lastMinutePrice,
                int daysBeforeLastMinute) :base(baseInfo)
            {
                OrganisationId = orgId;
                EventProductId = eventProductId;
                LocationId = locationId;
                Type = type;
                MaxAttendees = maxAttendees;
                CurrencyCode = currencyCode;
                Price = price;
                LastMinutePrice = lastMinutePrice;
                DaysBeforeLastMinute = daysBeforeLastMinute;
            }
      
        }
    }

    For the Wcf Service class I also used one of your examples:

    namespace myoWebRole.WCF
    {   
        [ServiceContract(Namespace = "")]
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        [ServiceBehavior(IncludeExceptionDetailInFaults = true)]   
        public class SchedulerWcfService : ISchedulerWcfService
        {
            private WebServiceAppointmentController _controller;
             
            private WebServiceAppointmentController Controller
            {
                get
                {               
                    if (_controller == null)
                    {
                        _controller =
                            new WebServiceAppointmentController(new MyobisSchedulerProvider());
                    }
                    return _controller;
                }
            }
              
            [OperationContract]             
            public IEnumerable<AppointmentData> GetAppointments(MyobisSchedulerInfo schedulerInfo)
            {
                return Controller.GetAppointments(schedulerInfo);
            }
      
            [OperationContract]       
            public IEnumerable<AppointmentData> InsertAppointment(MyobisSchedulerInfo schedulerInfo, AppointmentData appointmentData)
            {
                return Controller.InsertAppointment(schedulerInfo, appointmentData);
            }
      
            [OperationContract]       
            public IEnumerable<AppointmentData> UpdateAppointment(MyobisSchedulerInfo schedulerInfo, AppointmentData appointmentData)
            {
                return Controller.UpdateAppointment(schedulerInfo, appointmentData);
            }
      
            [OperationContract]      
            public IEnumerable<AppointmentData> DeleteAppointment(MyobisSchedulerInfo schedulerInfo, AppointmentData appointmentData, bool deleteSeries)
            {
                return Controller.DeleteAppointment(schedulerInfo, appointmentData, deleteSeries);
            }
      
            [OperationContract]      
            public IEnumerable<ResourceData> GetResources(MyobisSchedulerInfo schedulerInfo)
            {           
                return Controller.GetResources(schedulerInfo);
            }
        }
    }

    in my web.config I register the Wcf Service:

    <system.serviceModel>
        <behaviors>     
          <endpointBehaviors>
            <behavior name="SchedulerWcfServiceAspNetAjaxBehavior">
              <enableWebScript/>
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true"/>   
        <services>
          <service name="SchedulerWcfService">
            <endpoint address="" behaviorConfiguration="SchedulerWcfServiceAspNetAjaxBehavior" contract="ISchedulerWcfService"/>
          </service>
        </services>    
    </system.serviceModel>

    The RadScheduler in my Scheduler.aspx site gets the following setting:
    <WebServiceSettings Path="../../WCF/SchedulerWcfService.svc"  ResourcePopulationMode="ServerSide"  />

    I am not using any javascript for appointmentPopulating etc.

    When I run my Site with the Radscheduler I get the following Exception:

    Source Error:
      
    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
      
    Stack Trace:
      
    [WebException: Der Remoteserver hat einen Fehler zurückgegeben: (404) Nicht gefunden.]
       System.Net.WebClient.UploadDataInternal(Uri address, String method, Byte[] data, WebRequest& request) +2716592
       System.Net.WebClient.UploadString(Uri address, String method, String data) +266
       Telerik.Web.UI.SchedulerWebServiceClient.GetResources() +653
      
    [Exception: An error occurred while requesting resources from the web service. Server responded with: ]
       Telerik.Web.UI.SchedulerWebServiceClient.GetResources() +1225
       Telerik.Web.UI.RadScheduler.BindResourcesFromWebService() +102
       Telerik.Web.UI.RadScheduler.PerformSelect() +117
       Telerik.Web.UI.RadScheduler.CreateChildControls(Boolean bindFromDataSource) +81
       System.Web.UI.Control.EnsureChildControls() +182
       System.Web.UI.Control.PreRenderRecursiveInternal() +60
       System.Web.UI.Control.PreRenderRecursiveInternal() +222
       System.Web.UI.Control.PreRenderRecursiveInternal() +222
       System.Web.UI.Control.PreRenderRecursiveInternal() +222
       System.Web.UI.Control.PreRenderRecursiveInternal() +222
       System.Web.UI.Control.PreRenderRecursiveInternal() +222
       System.Web.UI.Control.PreRenderRecursiveInternal() +222
       System.Web.UI.Control.PreRenderRecursiveInternal() +222
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +4185


    I found out that this happens due to the Property ResourcePopulationMode="ServerSide" of the WebServiceSetting.
    Deleting this Property I can see the Scheduler but with an alert box saying: "The server method 'Get Resources' failed" and "The server method 'GetAPpointments' failed.

    My suspicion is that either my implementation of the DbSchedulerProviderBase is wrong or my Settings in the web.config is wrong.

    Any idea?

    Thanks,

  2. Peter
    Admin
    Peter avatar
    6637 posts

    Posted 17 Feb 2011 Link to this post

    Hello sortep,

    Probably, the problem is that you use WCF Service instead of Ajax-enabled WCF service. Please, see step 3 from this help topic:

    3. Add the WCF service – right click on your project in the Solution Explorer and select Add New Item. This is important: select the Ajax-enabled WCF service option (do not mix it with WCF Service):

    Also, the GetResources method should look like this:

    public override IDictionary<ResourceType, IEnumerable<Resource>> GetResources(ISchedulerInfo schedulerInfo)
           {
               Dictionary<ResourceType, IEnumerable<Resource>> resCollection = new Dictionary<ResourceType, IEnumerable<Resource>>();
               //resCollection.Add(new ResourceType("Teacher", false), Teachers.Values);
               //resCollection.Add(new ResourceType("Student", true), Students.Values);
               return resCollection;
           }

    Attached is a sample project for reference.


    Regards,
    Peter
    the Telerik team
Back to Top