Base solution for your next web application
Open Closed

Creating an Entity Import from Excel, 404 when it tries to upload. #9122


User avatar
0
marble68 created

Using v8.7 Jquery

I'm attempting to provide a way for my users to import an Entity (Taker) with excel.

I'm going through the User Import from excel as an example, along with the ABP documentation here: https://aspnetboilerplate.com/Pages/Documents/Background-Jobs-And-Workers

I created an ImportTakerDto - providing the exception and CanBeImported method, along with my properties.

I added a custommapper DTO.

I created a class for background job arguments.

I then created a background job, added a new TakersControllerBase. I then modified my TakerController to inherit from the base.

I added the import to excel buttons, and updated the index.js for Takers.

However, I get a 404 when calling it.

I've verified the auth token is there in the request header.

I've run npm run create-bundles on MVC, cleaned and rebuilt the project.

What should I check? Everything builds and runs - the only issue is when it tries to call my ImportFromExcel function on my TakerController it fails.

Thanks for any tips to check.


8 Answer(s)
  • User Avatar
    0
    marble68 created

    I updated the TakerController in both MVC and Host.

  • User Avatar
    0
    marble68 created

    Im still getting a 404.

    ive tried changing authorization but still 404s.

    is there a route or something i have to do to get the method to process?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @marble68

    Could you share your

    1. TakerController
    2. Related cshtml page
    3. Related Js file

    Thanks,

  • User Avatar
    0
    marble68 created

    Do you want me to email or post here?

  • User Avatar
    0
    marble68 created

    TakerController:

    using System;
    using System.Threading.Tasks;
    using Abp.AspNetCore.Mvc.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using okto.work.Web.Areas.App.Models.Takers;
    using okto.work.Web.Controllers;
    using okto.work.Authorization;
    using okto.work.Chat;
    using okto.work.Chat.Dtos;
    using Abp.Application.Services.Dto;
    using Abp.Extensions;
    using okto.work.Storage;
    using Abp.BackgroundJobs;
    
    namespace okto.work.Web.Areas.App.Controllers
    {
        [Area("App")]
        [AbpMvcAuthorize(AppPermissions.Pages_Takers)]
        public class TakersController : TakersControllersBase //workControllerBase
        {
            private readonly ITakersAppService _takersAppService;
    
            public TakersController(IBinaryObjectManager binaryObjectManager, IBackgroundJobManager backgroundJobManager, ITakersAppService takersAppService)
                : base(binaryObjectManager, backgroundJobManager)
            {
                _takersAppService = takersAppService;
            }
    
            public ActionResult Index()
            {
                var model = new TakersViewModel
                {
                    FilterText = ""
                };
    
                return View(model);
            }
    
    
            [AbpMvcAuthorize(AppPermissions.Pages_Takers_Create, AppPermissions.Pages_Takers_Edit)]
            public async Task<PartialViewResult> CreateOrEditModal(Guid? id)
            {
                GetTakerForEditOutput getTakerForEditOutput;
    
                if (id.HasValue)
                {
                    getTakerForEditOutput = await _takersAppService.GetTakerForEdit(new EntityDto<Guid> { Id = (Guid)id });
                }
                else
                {
                    getTakerForEditOutput = new GetTakerForEditOutput
                    {
                        Taker = new CreateOrEditTakerDto()
                    };
                    getTakerForEditOutput.Taker.dateCleared = DateTime.Now;
                    getTakerForEditOutput.Taker.dateClearExpires = DateTime.Now;
                    getTakerForEditOutput.Taker.dateLastSurvey = DateTime.Now;
                }
    
                var viewModel = new CreateOrEditTakerModalViewModel()
                {
                    Taker = getTakerForEditOutput.Taker,
                };
    
                return PartialView("_CreateOrEditModal", viewModel);
            }
    
    
            public async Task<PartialViewResult> ViewTakerModal(Guid id)
            {
                var getTakerForViewDto = await _takersAppService.GetTakerForView(id);
    
                var model = new TakerViewModel()
                {
                    Taker = getTakerForViewDto.Taker
                };
    
                return PartialView("_ViewTakerModal", model);
            }
    
    
        }
    }
    
  • User Avatar
    0
    marble68 created

    index.cshtml for Takers:

    @using okto.work.Authorization
    @using okto.work.Web.Areas.App.Models.Takers
    @using okto.work.Web.Areas.App.Startup
    @model TakersViewModel
    @{
        ViewBag.CurrentPageName = AppPageNames.Common.Takers;
    }
    @section Scripts
    {
        <script abp-src="/view-resources/Areas/App/Views/Takers/Index.js" asp-append-version="true"></script>
    }
    <div class="kt-content  kt-grid__item kt-grid__item--fluid kt-grid kt-grid--hor">
     <div class="kt-subheader kt-grid__item">
      <div class="@(await GetContainerClass())">
        <div class="kt-subheader__main">
            <h3 class="kt-subheader__title">
                <span>@L("Takers")</span>
            </h3>
            <span class="kt-subheader__separator kt-subheader__separator--v"></span>
            <span class="kt-subheader__desc">
                @L("TakersHeaderInfo")
            </span>
        </div>
        <div class="kt-subheader__toolbar">
            <div class="kt-subheader__wrapper">
                <div class="btn-group">
                    <button type="button" class="btn btn-outline-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        <i class="far fa-file-excel"></i> @L("ExcelOperations")
                    </button>
                    <div class="dropdown-menu dropdown-menu-right">
                        <a class="dropdown-item" id="ExportTakersToExcelButton" href="#"> @L("ExportToExcel")</a>
                        <a class="dropdown-item" href="#">
                            <span class="fileinput-button">
                                <span>@L("ImportFromExcel")</span>
                                <input id="ImportTakersFromExcelButton" type="file" name="files" accept=".xlsx, .xls, .csv">
                            </span>
                        </a>
                        <div class="dropdown-divider"></div>
                        <span class="dropdown-item-text text-muted pl-3" href="#">
                            <small class="pl-2"> @Html.Raw(L("ImportToExcelSampleFileDownloadInfo", "<a href='" + (ApplicationPath) + "assets/SampleFiles/ImportUsersSampleFile.xlsx" + "'>" + L("ClickHere") + "</a>"))</small>
                        </span>
                    </div>
                </div>
                @*<button id="ExportToExcelButton" class="btn btn-outline-success"><i class="fa fa-file-excel"></i> @L("ExportToExcel")</button>*@
                @if (IsGranted(AppPermissions.Pages_Takers_Create))
                {
                    <button id="CreateNewTakerButton" class="btn btn-primary blue"><i class="fa fa-plus"></i> @L("CreateNewTaker")</button>
                }
            </div>
        </div>
      </div>
    </div>
    <div class="@(await GetContainerClass()) kt-grid__item kt-grid__item--fluid">
        <div class="kt-portlet kt-portlet--mobile">
            <div class="kt-portlet__body">
                <div class="kt-form">
                    <div class="row align-items-center mb-4">
                        <div class="col-xl-12">
                            <div class="form-group align-items-center">
                                <div class="input-group">
                                    <input type="text" id="TakersTableFilter" class="form-control m-input" placeholder="@L("SearchWithThreeDot")" value="@Model.FilterText">
                                    <span class="input-group-btn">
                                        <button id="GetTakersButton" class="btn btn-primary" type="submit"><i class="flaticon-search-1"></i></button>
                                    </span>
                                </div>
                            </div>
                        </div>
                    </div>
    			</div>
                    <div id="AdvacedAuditFiltersArea" style="display: none" class="row mb-4">
                        <div class="col-md-12">
    						<div class="kt-separator kt-separator--border-dashed"></div>
    					</div>
    
    							<div class="col-md-3">
    								<div class="form-group">
    									<label for="firstNameFilterId">@L("firstName")</label>
    									<input type="text" class="form-control" name="firstNameFilter" id="firstNameFilterId">
    								</div>
                                </div>
    							<div class="col-md-3">
    								<div class="form-group">
    									<label for="lastNameFilterId">@L("lastName")</label>
    									<input type="text" class="form-control" name="lastNameFilter" id="lastNameFilterId">
    								</div>
                                </div>
    							<div class="col-md-3">
    								<div class="form-group">
    									<label for="cellFilterId">@L("cell")</label>
    									<input type="text" class="form-control" name="cellFilter" id="cellFilterId">
    								</div>
                                </div>
    							<div class="col-md-3">
    								<div class="form-group">
    									<label for="emailFilterId">@L("email")</label>
    									<input type="text" class="form-control" name="emailFilter" id="emailFilterId">
    								</div>
                                </div>
    							<div class="col-md-3">
    								<label for="isclearFilterId">@L("isclear")</label>
    								<select class="form-control" name="isclearFilter" id="isclearFilterId">
    									<option value="-1">@L("All")</option>
    									<option value="0">@L("False")</option>
    									<option value="1">@L("True")</option>
    								</select>
                                </div>
                                <div class="col-md-3">
                                        <div class="form-group">
    										<label for="MindateClearedFilterId">@L("dateClearedRange")</label>
    										<div class="input-group">
    											<input class="form-control m-input date-picker" type="text" placeholder="@L("MinValue")"  id="MindateClearedFilterId">
    											<span style="line-height: 40px;padding: 0 15px 0 15px;"> &mdash; </span>
    											<input class="form-control m-input date-picker" type="text" placeholder="@L("MaxValue")"  id="MaxdateClearedFilterId">
    										</div>
    									</div>
                                </div>
                                <div class="col-md-3">
                                        <div class="form-group">
    										<label for="MindateClearExpiresFilterId">@L("dateClearExpiresRange")</label>
    										<div class="input-group">
    											<input class="form-control m-input date-picker" type="text" placeholder="@L("MinValue")"  id="MindateClearExpiresFilterId">
    											<span style="line-height: 40px;padding: 0 15px 0 15px;"> &mdash; </span>
    											<input class="form-control m-input date-picker" type="text" placeholder="@L("MaxValue")"  id="MaxdateClearExpiresFilterId">
    										</div>
    									</div>
                                </div>
                                <div class="col-md-3">
                                        <div class="form-group">
    										<label for="MindateLastSurveyFilterId">@L("dateLastSurveyRange")</label>
    										<div class="input-group">
    											<input class="form-control m-input date-picker" type="text" placeholder="@L("MinValue")"  id="MindateLastSurveyFilterId">
    											<span style="line-height: 40px;padding: 0 15px 0 15px;"> &mdash; </span>
    											<input class="form-control m-input date-picker" type="text" placeholder="@L("MaxValue")"  id="MaxdateLastSurveyFilterId">
    										</div>
    									</div>
                                </div>
    							<div class="col-md-3">
    								<div class="form-group">
    									<label for="surveyIdentKeyFilterId">@L("surveyIdentKey")</label>
    									<input type="text" class="form-control" name="surveyIdentKeyFilter" id="surveyIdentKeyFilterId">
    								</div>
                                </div>
    							<div class="col-md-3">
    								<label for="wasManuallyClearedFilterId">@L("wasManuallyCleared")</label>
    								<select class="form-control" name="wasManuallyClearedFilter" id="wasManuallyClearedFilterId">
    									<option value="-1">@L("All")</option>
    									<option value="0">@L("False")</option>
    									<option value="1">@L("True")</option>
    								</select>
                                </div>
    							<div class="col-md-3">
    								<div class="form-group">
    									<label for="wasManuallyClearedReasonFilterId">@L("wasManuallyClearedReason")</label>
    									<input type="text" class="form-control" name="wasManuallyClearedReasonFilter" id="wasManuallyClearedReasonFilterId">
    								</div>
                                </div>
    							<div class="col-md-3">
    								<div class="form-group">
    									<label for="wasManuallyClearedOnFilterId">@L("wasManuallyClearedOn")</label>
    									<input type="text" class="form-control" name="wasManuallyClearedOnFilter" id="wasManuallyClearedOnFilterId">
    								</div>
                                </div>
    							<div class="col-md-3">
    								<div class="form-group">
    									<label for="wasManuallyClearedByFilterId">@L("wasManuallyClearedBy")</label>
    									<input type="text" class="form-control" name="wasManuallyClearedByFilter" id="wasManuallyClearedByFilterId">
    								</div>
                                </div>
    							<div class="col-md-3">
    								<div class="form-group">
    									<label for="wasManuallyCleardByIdFilterId">@L("wasManuallyCleardById")</label>
    									<input type="text" class="form-control" name="wasManuallyCleardByIdFilter" id="wasManuallyCleardByIdFilterId">
    								</div>
                                </div>
    
                    </div>
                    <div class="row mb-4">
                        <div class="col-xl-12">
                            <span id="ShowAdvancedFiltersSpan" class="text-muted clickable-item"><i class="fa fa-angle-down"></i> @L("ShowAdvancedFilters")</span>
                            <span id="HideAdvancedFiltersSpan" class="text-muted clickable-item" style="display: none"><i class="fa fa-angle-up"></i> @L("HideAdvancedFilters")</span>
                        </div>
                    </div>
                <div class="row align-items-center">
                    <table id="TakersTable" class="display table table-striped table-bordered table-hover dt-responsive nowrap">
                        <thead>
                            <tr>
                                <th>@L("Actions")</th>
    								<th>@L("firstName")</th>
    								<th>@L("lastName")</th>
    								<th>@L("cell")</th>
    								<th>@L("email")</th>
    								<th>@L("isclear")</th>
    								<th>@L("dateCleared")</th>
    								<th>@L("dateClearExpires")</th>
    								<th>@L("dateLastSurvey")</th>
    								<th>@L("surveyIdentKey")</th>
    								<th>@L("wasManuallyCleared")</th>
    								<th>@L("wasManuallyClearedReason")</th>
    								<th>@L("wasManuallyClearedOn")</th>
    								<th>@L("wasManuallyClearedBy")</th>
    								<th>@L("wasManuallyCleardById")</th>
                            </tr>
                        </thead>
                    </table>
                </div>
            </div>
        </div>
      </div>
    </div>
    
  • User Avatar
    0
    marble68 created

    index.js for Takers:

    (function () {
        $(function () {
    
            var _$takersTable = $('#TakersTable');
            var _takersService = abp.services.app.takers;
    		
            $('.date-picker').datetimepicker({
                locale: abp.localization.currentLanguage.name,
                format: 'L'
            });
    
            var _permissions = {
                create: abp.auth.hasPermission('Pages.Takers.Create'),
                edit: abp.auth.hasPermission('Pages.Takers.Edit'),
                'delete': abp.auth.hasPermission('Pages.Takers.Delete')
            };
    
             var _createOrEditModal = new app.ModalManager({
                viewUrl: abp.appPath + 'App/Takers/CreateOrEditModal',
                scriptUrl: abp.appPath + 'view-resources/Areas/App/Views/Takers/_CreateOrEditModal.js',
                modalClass: 'CreateOrEditTakerModal'
            });       
    
    		 var _viewTakerModal = new app.ModalManager({
                viewUrl: abp.appPath + 'App/Takers/ViewtakerModal',
                modalClass: 'ViewTakerModal'
            });
    
    		
    		
    
            var getDateFilter = function (element) {
                if (element.data("DateTimePicker").date() == null) {
                    return null;
                }
                return element.data("DateTimePicker").date().format("YYYY-MM-DDT00:00:00Z"); 
            }
    
            var dataTable = _$takersTable.DataTable({
                paging: true,
                serverSide: true,
                processing: true,
                listAction: {
                    ajaxFunction: _takersService.getAll,
                    inputFilter: function () {
                        return {
    					filter: $('#TakersTableFilter').val(),
    					firstNameFilter: $('#firstNameFilterId').val(),
    					lastNameFilter: $('#lastNameFilterId').val(),
    					cellFilter: $('#cellFilterId').val(),
    					emailFilter: $('#emailFilterId').val(),
    					isclearFilter: $('#isclearFilterId').val(),
    					mindateClearedFilter:  getDateFilter($('#MindateClearedFilterId')),
    					maxdateClearedFilter:  getDateFilter($('#MaxdateClearedFilterId')),
    					mindateClearExpiresFilter:  getDateFilter($('#MindateClearExpiresFilterId')),
    					maxdateClearExpiresFilter:  getDateFilter($('#MaxdateClearExpiresFilterId')),
    					mindateLastSurveyFilter:  getDateFilter($('#MindateLastSurveyFilterId')),
    					maxdateLastSurveyFilter:  getDateFilter($('#MaxdateLastSurveyFilterId')),
    					surveyIdentKeyFilter: $('#surveyIdentKeyFilterId').val(),
    					wasManuallyClearedFilter: $('#wasManuallyClearedFilterId').val(),
    					wasManuallyClearedReasonFilter: $('#wasManuallyClearedReasonFilterId').val(),
    					wasManuallyClearedOnFilter: $('#wasManuallyClearedOnFilterId').val(),
    					wasManuallyClearedByFilter: $('#wasManuallyClearedByFilterId').val(),
    					wasManuallyCleardByIdFilter: $('#wasManuallyCleardByIdFilterId').val()
                        };
                    }
                },
                columnDefs: [
                    {
                        width: 120,
                        targets: 0,
                        data: null,
                        orderable: false,
                        autoWidth: false,
                        defaultContent: '',
                        rowAction: {
                            cssClass: 'btn btn-brand dropdown-toggle',
                            text: '<i class="fa fa-cog"></i> ' + app.localize('Actions') + ' <span class="caret"></span>',
                            items: [
    						{
                                    text: app.localize('View'),
                                    action: function (data) {
                                        _viewTakerModal.open({ id: data.record.taker.id });
                                    }
                            },
    						{
                                text: app.localize('Edit'),
                                visible: function () {
                                    return _permissions.edit;
                                },
                                action: function (data) {
                                _createOrEditModal.open({ id: data.record.taker.id });                                
                                }
                            }, 
    						{
                                text: app.localize('Delete'),
                                visible: function () {
                                    return _permissions.delete;
                                },
                                action: function (data) {
                                    deleteTaker(data.record.taker);
                                }
                            }]
                        }
                    },
    					{
    						targets: 1,
    						 data: "taker.firstName",
    						 name: "firstName"   
    					},
    					{
    						targets: 2,
    						 data: "taker.lastName",
    						 name: "lastName"   
    					},
    					{
    						targets: 3,
    						 data: "taker.cell",
    						 name: "cell"   
    					},
    					{
    						targets: 4,
    						 data: "taker.email",
    						 name: "email"   
    					},
    					{
    						targets: 5,
    						 data: "taker.isclear",
    						 name: "isclear"  ,
    						render: function (isclear) {
    							if (isclear) {
    								return '<div class="text-center"><i class="fa fa-check kt--font-success" title="True"></i></div>';
    							}
    							return '<div class="text-center"><i class="fa fa-times-circle" title="False"></i></div>';
    					}
    			 
    					},
    					{
    						targets: 6,
    						 data: "taker.dateCleared",
    						 name: "dateCleared" ,
    					render: function (dateCleared) {
    						if (dateCleared) {
    							return moment(dateCleared).format('L');
    						}
    						return "";
    					}
    			  
    					},
    					{
    						targets: 7,
    						 data: "taker.dateClearExpires",
    						 name: "dateClearExpires" ,
    					render: function (dateClearExpires) {
    						if (dateClearExpires) {
    							return moment(dateClearExpires).format('L');
    						}
    						return "";
    					}
    			  
    					},
    					{
    						targets: 8,
    						 data: "taker.dateLastSurvey",
    						 name: "dateLastSurvey" ,
    					render: function (dateLastSurvey) {
    						if (dateLastSurvey) {
    							return moment(dateLastSurvey).format('L');
    						}
    						return "";
    					}
    			  
    					},
    					{
    						targets: 9,
    						 data: "taker.surveyIdentKey",
    						 name: "surveyIdentKey"   
    					},
    					{
    						targets: 10,
    						 data: "taker.wasManuallyCleared",
    						 name: "wasManuallyCleared"  ,
    						render: function (wasManuallyCleared) {
    							if (wasManuallyCleared) {
    								return '<div class="text-center"><i class="fa fa-check kt--font-success" title="True"></i></div>';
    							}
    							return '<div class="text-center"><i class="fa fa-times-circle" title="False"></i></div>';
    					}
    			 
    					},
    					{
    						targets: 11,
    						 data: "taker.wasManuallyClearedReason",
    						 name: "wasManuallyClearedReason"   
    					},
    					{
    						targets: 12,
    						 data: "taker.wasManuallyClearedOn",
    						 name: "wasManuallyClearedOn"   
    					},
    					{
    						targets: 13,
    						 data: "taker.wasManuallyClearedBy",
    						 name: "wasManuallyClearedBy"   
    					},
    					{
    						targets: 14,
    						 data: "taker.wasManuallyCleardById",
    						 name: "wasManuallyCleardById"   
    					}
                ]
            });
    
            function getTakers() {
                dataTable.ajax.reload();
            }
    
            function deleteTaker(taker) {
                abp.message.confirm(
                    '',
                    app.localize('AreYouSure'),
                    function (isConfirmed) {
                        if (isConfirmed) {
                            _takersService.delete({
                                id: taker.id
                            }).done(function () {
                                getTakers(true);
                                abp.notify.success(app.localize('SuccessfullyDeleted'));
                            });
                        }
                    }
                );
            }
    
    		$('#ShowAdvancedFiltersSpan').click(function () {
                $('#ShowAdvancedFiltersSpan').hide();
                $('#HideAdvancedFiltersSpan').show();
                $('#AdvacedAuditFiltersArea').slideDown();
            });
    
            $('#HideAdvancedFiltersSpan').click(function () {
                $('#HideAdvancedFiltersSpan').hide();
                $('#ShowAdvancedFiltersSpan').show();
                $('#AdvacedAuditFiltersArea').slideUp();
            });
    
            $('#CreateNewTakerButton').click(function () {
                _createOrEditModal.open();
            });        
    
    		$('#ExportTakersToExcelButton').click(function () {
                _takersService
                    .getTakersToExcel({
    				filter : $('#TakersTableFilter').val(),
    					firstNameFilter: $('#firstNameFilterId').val(),
    					lastNameFilter: $('#lastNameFilterId').val(),
    					cellFilter: $('#cellFilterId').val(),
    					emailFilter: $('#emailFilterId').val(),
    					isclearFilter: $('#isclearFilterId').val(),
    					mindateClearedFilter:  getDateFilter($('#MindateClearedFilterId')),
    					maxdateClearedFilter:  getDateFilter($('#MaxdateClearedFilterId')),
    					mindateClearExpiresFilter:  getDateFilter($('#MindateClearExpiresFilterId')),
    					maxdateClearExpiresFilter:  getDateFilter($('#MaxdateClearExpiresFilterId')),
    					mindateLastSurveyFilter:  getDateFilter($('#MindateLastSurveyFilterId')),
    					maxdateLastSurveyFilter:  getDateFilter($('#MaxdateLastSurveyFilterId')),
    					surveyIdentKeyFilter: $('#surveyIdentKeyFilterId').val(),
    					wasManuallyClearedFilter: $('#wasManuallyClearedFilterId').val(),
    					wasManuallyClearedReasonFilter: $('#wasManuallyClearedReasonFilterId').val(),
    					wasManuallyClearedOnFilter: $('#wasManuallyClearedOnFilterId').val(),
    					wasManuallyClearedByFilter: $('#wasManuallyClearedByFilterId').val(),
    					wasManuallyCleardByIdFilter: $('#wasManuallyCleardByIdFilterId').val()
    				})
                    .done(function (result) {
                        app.downloadTempFile(result);
                    });
            });
    		$('#ImportTakersFromExcelButton').fileupload({
    			url: abp.appPath + 'Takers/ImportFromExcel',
    			dataType: 'json',
    			maxFileSize: 1048576 * 100,
    			dropZone: $('#TakersTable'),
    			done: function (e, response) {
    				var jsonResult = response.result;
    				if (jsonResult.success) {
    					abp.notify.info(app.localize('ImportTakersProcessStart'));
    				} else {
    					abp.notify.warn(app.localize('ImportTakersUploadFailed'));
    				}
    			}
    		}).prop('disabled', !$.support.fileInput)
    			.parent().addClass($.support.fileInput ? undefined : 'disabled');
    
            abp.event.on('app.createOrEditTakerModalSaved', function () {
                getTakers();
            });
    
    		$('#GetTakersButton').click(function (e) {
                e.preventDefault();
                getTakers();
            });
    
    		$(document).keypress(function(e) {
    		  if(e.which === 13) {
    			getTakers();
    		  }
    		});
        });
    })();
    
  • User Avatar
    0
    marble68 created

    I feel foolish - but apparently when calling the controllers you have to call /App/<controller>/Method when not using the service.

    The UsersController lives off the root in controllers, while my Taker controller is the areas.

    Modifying my index.js to post to /app/Takers/ImportFromExcel worked hit my breakpoint.

    Sorry for my ignorance, you can close this.