Managing CRUD operations

Managing CRUD operations

Basic Principles

The library doesn't provide automatic processing of create/update/delete operations but provides classes to render the response for the scheduler.
That's why you should specify CRUD logic manually.

2 main things you should know for successful processing of queries:

  1. To parse a request you should use the DHTMLX.Common.DataAction class.

    DataAction properties:

    • Type - the type of an action. Possible values are:
      • inserted;
      • deleted;
      • updated;
      • error.
    • SourceId - the ID assigned to an item at the beginning of the action.
    • TargetId - the ID assigned to an item after the action is finished. The parameters are differ just in case of insert operation. In this case, SourceID is the id generated on the client-side and TargetId is the id of an event in the database.

  2. To render the response you should use the DHTMLX.Common.AjaxSaveResponse class.
    The constructor of AjaxSaveResponse takes a DataAction object as an argument.

By default, the DHTMLX.Common.DataAction class expects the item id to have the Integer type. But if you need you can use other types, such as String or Guid.
To set a class different from Integer for the ID field you should use generic of the DataAction class:

var action = new DataAction<Guid>(actionValues);

Helpers

The library provides special helpers (the DHTMLX.Common.DHXEventsHelper class) that especially can come in use when you develop a usual ASP.NET project (but for MVC projects they are also helpful).

So, these helpers are:

  • Bind() - builds an object by taking values from the related request and converting them to the appropriate data type (analog to MVC model binder). In the CRUD logic it can be used to get the object of the changed event at once, not 'constructing' it from the values of individual fields.
  • Update() - updates one object with the properties' values from another one. It helps you to update the changed event by one command.

One more member of the class is the GetOccurrences() method. It's used for recurring events and you can know its details in the related chapter of the documentation - the Recurring events article.

Bind() method

The Bind() method has 2 overloads:

  1. public static object Bind(Type obj, NameValueCollection values);
  2. public static object Bind(Type obj, NameValueCollection values, CultureInfo culture);

As parameters the method takes:

  • obj - specifies the type which the object should have (note, that the object's class must have a default constructor);
  • values - the name-value collection;
  • culture - defines the locale settings (e.g. new CultureInfo(“en-US”) ).

Note, version 2.2 introduced generics for the Bind() method that made possible to call this method in the simplified form:

  1. public static T Bind<T>(NameValueCollection values);
  2. public static T Bind<T>(NameValueCollection values, CultureInfo culture);

Update() method

The Update() method has 2 overloads:

  1. public static void Update(object target, object source);
  2. public static void Update(object target, object source, List<string> except);

As parameters the method takes:

  • target - the object which should be updated;
  • source - the object which values of properties will be copied from;
  • except - the list of properties that should be excluded from the updating procedure.

With the helpers, the function implementing CRUD logic can look like the code below:

public ContentResult Save(int? id, FormCollection actionValues)
{
  var action = new DataAction(actionValues);
 
  DHXSchedulerDataContext data = new DHXSchedulerDataContext();
  try
   {
       var changedEvent = DHXEventsHelper.Bind<Event>(actionValues, new CultureInfo("en-US"));
       switch (action.Type)
       {
         case DataActionTypes.Insert:
                data.Events.InsertOnSubmit(changedEvent);
                break;
         case DataActionTypes.Delete:
                changedEvent = data.Events.SingleOrDefault(ev => ev.id == action.SourceId);
                data.Events.DeleteOnSubmit(changedEvent);
                break;
         default:// "update"                          
                var eventToUpdate = data.Events.SingleOrDefault(ev => ev.id == action.SourceId);
                DHXEventsHelper.Update(eventToUpdate, changedEvent, new List<string>() { "id" });
                break;
        }
        data.SubmitChanges();
        action.TargetId = changedEvent.id;
        }
            catch (Exception a)
        {
                action.Type = DataActionTypes.Error;
        }
 
        return (new AjaxSaveResponse(action));
}

 
Code samples included in the documentation (as well as the samples included in the package), use LINQ to SQL to access a database.

For each LINQ to SQL designer file added to the solution, Visual Studio automatically generates a LINQ to SQL DataContext class. DataContext class used in the code samples named as DHXSchedulerDataContext.

Common CRUD implementation

Helpers is a preferable approach but if you don't want to use it, you can implement CRUD logic in a general way, as shown in the code below:

public ContentResult Save(Event changedEvent, FormCollection actionValues)
        {
//initializes a DataAction object from request parameters
            var action = new DataAction(actionValues);
 
            DHXSchedulerDataContext data = new DHXSchedulerDataContext();
 
//Implementation create/update/delete operations. 
//Note, we use try-catch block to handle exceptions which may be thrown during operations. In this case, we must assign the error status to a DataAction object
//in order to mark the appropriate action on the client-side as failed.
            try
            {
                switch (action.Type)
                {
                    case DataActionTypes.Insert:
                        data.Events.InsertOnSubmit(changedEvent);
                        break;
                    case DataActionTypes.Delete:
                        changedEvent = data.Events.SingleOrDefault(ev => ev.id == action.SourceId);
                        data.Events.DeleteOnSubmit(changedEvent);
                        break;
                    default:// "update"                          
                        changedEvent = data.Events.SingleOrDefault(ev => ev.id == action.SourceId);
                        UpdateModel(changedEvent);
                        break;
                }
                data.SubmitChanges();
                action.TargetId = changedEvent.id;
            }
            catch (Exception a)
            {
                action.Type = DataActionTypes.Error;
            }
//renders a response using an AjaxSaveResponse object. AjaxSaveResponse can be initialized by a DataActionResult object and can be implicitly converted
//to the System.Web.Mvc.ContentResult type.
            return (new AjaxSaveResponse(action));
        }

Custom initial values for events

There is the possibility to set custom initial values for the event's properties. So, in cases when the user adds a new event, it will have values set by you.

To set custom initial values for new events you should use the DHXScheduler.InitialValues.Add(string propertyName, object defaultValue) method. The DHXScheduler.InitialValues class contains a collection of default values for an event.

For example, if you want to change the text of new events and have “I'm your new event!” instead of “New event” you can call the Add() method as in:

DHXScheduler.InitialValues.Add("text", "I'm your new event!");

 custom inital values for events

Postprocessing data properties on the server

In this part we'll consider how you can update singular property(es) on the client after common saving the data item on the server.

First of all, to be able to update properties apart from the whole data item, you should activate a special mode (that provides such an ability) as in:

public ActionResult Index()
{
    var scheduler = new DHXScheduler(this);
    ...
    scheduler.UpdateFieldsAfterSave();//this line activates the required mode
    ...
}

Then, to update the desired property(es) you should use one of the methods below (methods belong to the AjaxSaveResponse class):

  • UpdateField(string propertyName, object propertyValue) - updates a data singular property

    public ContentResult Save(int? id, FormCollection actionValues)
    {
    ...
       var response = new AjaxSaveResponse(action);
       response.UpdateField("propertyName", propertyValue);
     
       return (ContentResult)response;
    }

    After the client get the response from the server, it will update the 'propertyName' property of the modified data item to value 'propertyValue'.

  • UpdateFields(Dictionary<string,object> properties) - updates multiple data properties at once

    public ContentResult Save(int? id, FormCollection actionValues)
    {
    ...
       var response = new AjaxSaveResponse(action);
       response.UpdateFields(new Dictionary<string,object>{
                    {"propertyName", "propertyValue"},
                    {"propertyName2", "propertyValue2"}
       };
     
       return (ContentResult)response;
    }

Handling AJAX errors

In case of network errors or invalid server response, the client-side will fire "onSaveError" event, which can be captured with a JavaScript code:

scheduler.attachEvent("onSaveError", function(id, resp){
    dhtmlx.message("Failed to  update data");
})

See the event details here

REST mode

The component can work with the REST backend, which means that it can use an appropriate HTTP verb for each type of the operation - GET, POST, PUT, DELETE

This mode can be enabled by DHXScheduler.AjaxMode property:

var scheduler = new DHXScheduler();
scheduler.AjaxMode = TransactionModes.REST;
  • GET - load data - requests will be sent to the url specified in DHXScheduler.DataAction property.
  • POST, PUT, DELETE - add, update, delete item - requests will be sent to the url specified in DHXScheduler.SaveAction property

comments powered by Disqus