2

The problem:

I am trying to save events in a calendar by passing the content in ajax to my controller function. But I keep on getting null values being passed to my database. I have checked the console.log under Network tools in browsers and all of the data is null except EventId .

I know inserting the events into the database is working but it seems like the data being inserted is not being read by either Ajax or there's something wrong with my controller. Why do I keep on getting null values?

What the data in my database looks like after I saved the events

Here's my controller

 [HttpPost]
        public IActionResult SaveEvent(Event data)
        {
            var userId = _userManager.GetUserId(User);
            var status = false;

            if (string.IsNullOrEmpty(userId))
            {
                Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                return Json(new { Data = false, ErrorMessage = "no User Id!" });
            }

            if (data.EventId > 0)
            {
                //Update the event
                var v = db.Events.Where(a => a.EventId == data.EventId).FirstOrDefault();
                if (v != null)
                {
                    userId = data.UserId;
                    v.EventId = data.EventId;
                    v.Title = data.Title;
                    v.Counselor = data.Counselor;
                    v.Description = data.Description;
                    v.EventStart = data.EventStart;
                    v.EventEnd = data.EventEnd;
                    v.AllDay = data.AllDay;
                    v.ThemeColor = data.ThemeColor;
                }
            }
            else
            {
                db.Events.Add(data);
            }
            db.SaveChanges();
            status = true;
            return Json(new { Data = data,  status});
        }

This is my Event class:

public class Event     {         
  public string UserId { get; set; }         
  public int? EventId { get; set; }         
  public string Title { get; set; }         
  public string Description { get; set; }
  public string EventStart { get; set; }
  public string EventEnd { get; set; }
  public string Counselor { get; set; }
  public string ThemeColor { get; set; }
  public bool AllDay { get; set; }
}

and my Ajax function

 function GenerateCalender(events) {
        jq341('#calender').fullCalendar('destroy'); 
        jq341('#calender').fullCalendar({
            contentHeight: 400,
            defaultDate: new Date(),
            timeFormat: 'h(:mm)a',
            header: {
                left: 'prev,next today',
                center: 'title',
                right: 'month,basicWeek,basicDay,agenda'
            },
            eventLimit: true,
            eventColor: '#378006',
            events: events,
            eventClick: function (calEvent, jsEvent, view) {
                selectedEvent = calEvent;
                jq341('#myModal #eventTitle').text(calEvent.title);
                var description = jq341('<div />');
                description.append(jq341('<p />').html('<b>Start:</b>' + calEvent.start.format("DD-MMM-YYYY HH:mm a")));

                if (calEvent.end != null) {
                    description.append(jq341('<p/>').html('<b>End:</b>' + calEvent.end.format("DD-MMM-YYYY HH:mm a")));
                }
                description.append(jq341('<p />').html('<b>Description:</b>' + calEvent.description));
                jq341('#myModal #pDetails').empty().html(description);

                jq341('#myModal').modal();
            },
            selectable: true,
            select: function (start, end) {
                selectedEvent = {
                    userID: '',
                    eventID: 0,
                    title: '',
                    counselor: '',
                    start: start,
                    end: end,
                    description: '',
                    allDay: false,
                    color: ''
                };
                openAddEditForm();
                jq341('#calendar').fullCalendar('unselect');
            },
            editable: true,
            eventDrop: function (event) {
                var data = {
                    UserId: event.userID,
                    EventId: event.eventID,
                    Title: event.title,
                    Counselor: event.counselor,
                    EventStart: event.start.format('DD/MM/YYYY HH:mm A'),
                    EventEnd: event.end != null ? event.end.format('DD/MM/YYYY HH:mm A') : null,
                    Description: event.description,
                    AllDay: event.allDay,
                    ThemeColor: event.color,
                    
                };
                SaveEvent(data);
            }
        })
    }

        function openAddEditForm() {
            if (selectedEvent != null) {
                jq341('#hdEventID').val(selectedEvent.eventID);
                jq341('#hdUserID').val(selectedEvent.userID);
                jq341('#txtSubject').val(selectedEvent.title);
                jq341('#ddCounselor').val(selectedEvent.counselor);
                jq341('#txtStart').val(selectedEvent.start.format('DD/MM/YYYY HH:mm A'));
                jq341('#chkIsFullDay').prop("checked", selectedEvent.allDay || false);
                jq341('#chkIsFullDay').change();
                jq341('#txtEnd').val(selectedEvent.end != null ? selectedEvent.end.format('DD/MM/YYYY HH:mm A') : '');
                jq341('#txtDescription').val(selectedEvent.description);
                jq341('#ddThemeColor').val(selectedEvent.color);
            }
            jq341('#myModal').modal('hide');
            jq341('#myModalSave').modal();
        }

        jq341('#btnSave').click(function () {
            //Validation
            if (jq341('#txtSubject').val().trim() == "") {
                alert('Title required');
                return;
            }
            if (jq341('#txtStart').val().trim() == "") {
                alert('Start date required');
                return;
            }
            if (jq341('#chkIsFullDay').is(':checked') == false && jq341('#txtEnd').val().trim() == "") {
                alert('End date required');
                return;
            }
            else {
                var format_start = jq341('#txtStart').val().replace(' ', '-').split('-');
                var nowy_start = format_start[1] + '-' + format_start[0] + '-' + format_start[2] + ' ' + format_start[3];

                var format_end = jq341('#txtEnd').val().replace(' ', '-').split('-');
                var nowy_end = format_end[1] + '-' + format_end[0] + '-' + format_end[2] + ' ' + format_end[3];
            }

            //edited
            var data = {
                UserId: jq341('#hdUserID').val(),
                EventId: jq341('#hdEventID').val(),
                Title: jq341('#txtSubject').val().trim(),
                Counselor: jq341('#ddCounselor').val(),
                EventStart: jq341('#txtStart').val().trim(),
                EventEnd: jq341('#chkIsFullDay').is(':checked') ? null : jq341('#txtEnd').val().trim(),
                Description: jq341('#txtDescription').val(),
                ThemeColor: jq341('#ddThemeColor').val(),
                AllDay: jq341('#chkIsFullDay').is(':checked')
            }
            alert(data);
            SaveEvent(data);
            // call function for submit data to the server
        })

    function SaveEvent(data) {
        jq341.ajax({
            type: "POST",
            contentType: "application/json; charset=utf-8",
            dataType: "JSON",
            url: '/Calendar/SaveEvent',
            data: JSON.stringify(data),
            success: function (data) {
                console.log(data)
                if (data.status) {
                    //Refresh the calender
                    FetchEventAndRenderCalendar();
                    jq341('#myModalSave').modal('hide');
                }
            },
            error: function () {
                alert('Failed', ErrorMessage);
            }
        })
    }

my cshtml

<div id="myModalSave" class="modal fade" role="dialog">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">&times;</button>
                <h4 class="modal-title">Appointments</h4>
            </div>

            <div class="modal-body">
                <form class="col-md-12 form-horizontal">
                    <input type="text" id="hdEventID" value="0" />
                    <input type="hidden" id="hdUserID">
                    <div class="form-group">
                        <label>Subject</label>
                        <input type="text" id="txtSubject" class="form-control" />
                    </div>

                    <div class="form-group">
                        <label>Counselor</label>
                        <select id="ddCounselor" class="form-control">
                            <option value="0">Choose your counselor</option>
                            <option value="DrSalwa">Dr Salwa</option>
                            <option value="DrNorzaiham">Dr Norzaiham</option>
                            <option value="Nasri">Sir Nasri</option>
                            <option value="Adibah">Ms. Adibah</option>
                        </select>
                    </div>

                    <div class="form-group">
                        <label>Start</label>
                        <div class="input-group date" id="dtp1">
                            <input type="text" id="txtStart" class="form-control" />
                            <span class="input-group-addon">
                                <span class="glyphicon glyphicon-calendar"></span>
                            </span>
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="checkbox">
                            <label><input type="checkbox" id="chkIsFullDay" checked="checked" />  Is Full Day event</label>
                        </div>
                    </div>
                    <div class="form-group" id="divEndDate" style="display:none">
                        <label>End</label>
                        <div class="input-group date" id="dtp2">
                            <input type="text" id="txtEnd" class="form-control" />
                            <span class="input-group-addon">
                                <span class="glyphicon glyphicon-calendar"></span>
                            </span>
                        </div>
                    </div>

                    <div class="form-group">
                        <label>Description</label>
                        <textarea id="txtDescription" rows="3" class="form-control"></textarea>
                    </div>
                    <div class="form-group">
                        <label>Theme Color</label>
                        <select id="ddThemeColor" class="form-control">
                            <option value="">Default</option>
                            <option value="red">Red</option>
                            <option value="blue">Blue</option>
                            <option value="black">Black</option>
                            <option value="green">Green</option>
                        </select>
                    </div>
                    <button type="button" id="btnSave" class="btn btn-success">Save</button>
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                </form>
            </div>
        </div>
    </div>
</div>

Below are screenshots of the Network tool Using [FormBody] but getting that null exception in if(data.eventId >0) in controller Using [FormBody] in Action

Below is [FormBody] is omitted from the controller but still getting null values except EventId Not using [FormBody] in Action

ADyson
  • 57,178
  • 14
  • 51
  • 63
anon_n5
  • 29
  • 6
  • Add `contentType: "application/json"` to your `$.ajax()` config – Phil Nov 20 '20 at 02:09
  • @Phil I already tried that, still getting null values :( – anon_n5 Nov 20 '20 at 02:13
  • Perhaps try using `public IActionResult SaveEvent([FromBody] Event data)` though from memory, that shouldn't be required. Providing the HTML for your form elements would also help with debugging – Phil Nov 20 '20 at 02:15
  • I already did that too but I got `System.NullReferenceException: 'Object reference not set to an instance of an object.'` by adding the `[FromBody]` @Phil – anon_n5 Nov 20 '20 at 02:20
  • So when you check the _Network_ console, what do you see in the request body? Any chance you could add a screenshot? (You can directly paste screenshots into the question editor) – Phil Nov 20 '20 at 02:24
  • Okay, I got you. I have posted the screenshots in my question, I see the values @Phil – anon_n5 Nov 20 '20 at 02:49
  • 1
    It's possible that the binder is unable to cast the submitted values, e.g. those dates. Can you show your Event class? – derloopkat Nov 20 '20 at 02:53
  • `public class Event { public string UserId { get; set; } public int? EventId { get; set; } public string Title { get; set; } public string Description { get; set; } public string EventStart { get; set; } public string EventEnd { get; set; } public string Counselor { get; set; } public string ThemeColor { get; set; } public bool AllDay { get; set; } } ` this is my Event class @derloopkat – anon_n5 Nov 20 '20 at 03:03
  • Put a breakpoint for your Visual studio debugger on the first line of the `public IActionResult SaveEvent` method. What is the value of `data` at that moment? Which, if any, of the properties are populated? – ADyson Nov 20 '20 at 10:10
  • 1
    _I got System.NullReferenceException: 'Object reference not set to an instance of an object.' by adding the [FromBody]_ ...which line exactly throws the error when you do that? Also, add the [FromBody] and then repeat the test with the debugger that I mentioned just above. Do you get different results, or the same? That's how you'll know whether that suggestion is relevant or not. (The object reference error may be coming later in the method as a result of a different problem, because maybe the code now takes a different path. You need to understand the cause and effect in more detail.) – ADyson Nov 20 '20 at 10:11

1 Answers1

1

First, you should add the [FromBody] attribute, otherwise the data will not be successfully obtained.

You can add a breakpoint in your action to observe whether the binding is successful.

Then, modify your db.Add() method, because your data contains EventId, and in your database I see EventId as the primary key, and your primary key is auto-incremented. If you add a New entity of EventId, then an exception will be thrown.

You can try change your action like below:

    [HttpPost]
    public IActionResult SaveEvent([FromBody]Event data)
    {
        var userId = _userManager.GetUserId(User);
        var status = false;

        if (string.IsNullOrEmpty(userId))
        {
            Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            return Json(new { Data = false, ErrorMessage = "no User Id!" });
        }

        if (data.EventId > 0)
        {
            //Update the event
            var v = db.Events.Where(a => a.EventId == data.EventId).FirstOrDefault();
            if (v != null)
            {
                userId = data.UserId;
                v.EventId = data.EventId;
                v.Title = data.Title;
                v.Counselor = data.Counselor;
                v.Description = data.Description;
                v.EventStart = data.EventStart;
                v.EventEnd = data.EventEnd;
                v.AllDay = data.AllDay;
                v.ThemeColor = data.ThemeColor;
            }
        }
        else
        {
            var data1 = new Event
            {
                UserId=data.UserId,
                Title = data.Title,
                Counselor = data.Counselor,
                Description = data.Description,
                EventStart = data.EventStart,
                EventEnd = data.EventEnd,
                AllDay = data.AllDay,
                ThemeColor = data.ThemeColor,
            };
            db.Events.Add(data1);
        }
        db.SaveChanges();
        status = true;
        return Json(new { Data = data,  status});
    }
Yinqiu
  • 6,609
  • 1
  • 6
  • 14
  • please explain what you changed, and more importantly _why_. Then everyone can a) see it clearly without having to work out what you did, and b) actually learn from it instead of just copying and hoping it works without fully knowing the reason. Code-only answers are not actually very helpful to the community. Thanks. – ADyson Nov 20 '20 at 10:09