Search code examples
c#umbracoumbraco8

contentService.SaveAndPublish not creating new content programmatically - Umbraco 8


hoping some one here can help me out with this one.

I am migrating our current Umbraco 7 project to Umbraco 8.

We have a custom back office section that uploads a CSV and creates new content from the CSV rows. The code seems to run fine and creates/saves the content. However it does not appear in the back office or in the database when I check.

The controller which has the method below is inheriting from UmbracoAuthorizedApiController

public async Task<HttpResponseMessage> UploadFileToServer()
{
    if (!Request.Content.IsMimeMultipartContent())
    {
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    }

    //Id for the parent
    var vehicleList = Umbraco.Content(2873);

    var provider = new MultipartMemoryStreamProvider();
    await Request.Content.ReadAsMultipartAsync(provider);
    var file = provider.Contents.First();
    var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
    _logger.Debug(this.GetType(), $"uploading file {filename}");

    var buffer = await file.ReadAsByteArrayAsync();
    var stream = new MemoryStream(buffer);
    string payload;
    using (var s = new StreamReader(stream))
    {
        var DataReader = new DataReader();
        var validateResult = DataReader.Validate(filename, s);

        if (validateResult.ImportedOK)
        {
            _logger.Debug(this.GetType(), $"file {filename} has no duplicates");
            IDataTypeService dts = Services.DataTypeService;
            var stocklistStatus = dts.GetAll().First(z => z.Name == "StocklistStatus");

            var dataType = dts.GetDataType(stocklistStatus.Id);
            ValueListConfiguration prevalues = 
                (ValueListConfiguration)dataType.Configuration;
            int pendingstatus = prevalues
                .Items
                .Where(x => x.Value == "Pending")
                .Select(i => i.Id)
                .FirstOrDefault();

            var service = Services.ContentService;

            using (var scope = _scopeProvider.CreateScope())
            {
                var db = scope.Database;

                foreach (var item in validateResult.ImportRows)
                {
                    var cleanedreg = Utility.CleanReg(item.Reg);
                    var cleanedConverterUsername = item.Converter.TrimStart('0');
                    var guid = new Guid("e597cb94-727d-44d2-987c-2d6d8e3b73c2");

                    var vehicle = service
                        .Create(cleanedreg, guid, "Vehicle", Security.GetUserId()
                        .Result);

                    var alreadyExists = ArchiveVehicleDataProvider
                        .CheckIfVehicleSoldExpiredBefore(db, cleanedreg, _logger);
                    vehicle
                        .SetValue(Vehicle
                        .GetModelPropertyType(x => x.Colour)
                        .Alias, item.Colour);
                    vehicle
                        .SetValue(Vehicle
                        .GetModelPropertyType(x => x.Converter)
                        .Alias, cleanedConverterUsername);
                    vehicle
                        .SetValue(Vehicle
                        .GetModelPropertyType(x => x.Doors)
                        .Alias, item.Doors);
                    vehicle
                        .SetValue(Vehicle
                        .GetModelPropertyType(x => x.ElectricBelt)
                        .Alias, item.ElectricBelt);
                    vehicle
                        .SetValue(Vehicle
                        .GetModelPropertyType(x => x.Fuel)
                        .Alias, item.Fuel);
                    vehicle
                        .SetValue(Vehicle
                        .GetModelPropertyType(x => x.Make)
                        .Alias, item.Make);
                    vehicle
                        .SetValue(Vehicle
                        .GetModelPropertyType(x => x.Mileage)
                        .Alias, item.Mileage);
                    vehicle
                        .SetValue(Vehicle.GetModelPropertyType(x => x.Model)
                        .Alias, item.Model);
                    vehicle.SetValue(Vehicle
                        .GetModelPropertyType(x => x.AdditionalInformation)
                        .Alias, item.Additional);
                    vehicle
                        .SetValue(Vehicle
                        .GetModelPropertyType(x => x.Price)
                        .Alias, item.Price);
                    vehicle
                        .SetValue(Vehicle
                        .GetModelPropertyType(x => x.Seats)
                        .Alias, item.Seats);
                    vehicle
                        .SetValue(Vehicle
                        .GetModelPropertyType(x => x.PublishedDate)
                        .Alias, DateTime.Now);

                    var result = service.SaveAndPublish(vehicle);
                }
            }
        }
        _logger.Debug(this.GetType(), $"file {filename} loaded into database");
        payload = JsonConvert.SerializeObject(validateResult);

    }
    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StringContent(payload);
    return response;
}

When I check the logs under App_Data it seems to suggest the items are being published.

{
  "@t":"2023-03-30T12:39:46.2787407Z",
  "@mt":"Document {ContentName} (id={ContentId}) has been published.",
  "ContentName":"Vehicle123",
  "ContentId":0,
  "SourceContext":"Umbraco.Core.Services.Implement.ContentService",
  "ProcessId":10848,"ProcessName":"iisexpress",
  "ThreadId":5,"AppDomainId":2,
  "AppDomainAppId":"LMW3SVC2ROOT",
  "MachineName":"AT1149",
  "Log4NetLevel":"INFO ",
  "HttpRequestNumber":3,
  "HttpRequestId":"f61e2d8f-71ac-48a9-87ce-e4ed98354c58"
}

There are no errors and can't see any thing obvious when stepping through the code. Does anyone have any suggestions please?

Another strange behaviour I have just noticed with line

var result = service.SaveAndPublish(vehicle);

Will give the content an ID. I have let the code run and "create" the content and the first result had an ID of 48863. Although I am unable to see this in the DB or Umbraco.

I have then closed and restarted the project and run the same code using the same CSV. This time I was given an ID of 48873. Incremented by the exact record length of the last upload. So it appears that a record of the ID's is kept somewhere although I can't find. (This could be a red herring on the original issue however)

The import and entire project is being built in a separate project from the original v7 solution so there should be no references to the old v7 database.


Solution

  • As far as I can see, you're not "committing" the changes made in your scope, which might be why you're seeing things being created - they are likely getting rolled back again.

    So if you add something like scope.Complete() right after the foreach, it might do the trick?

    https://our.umbraco.com/apidocs/v8/csharp/api/Umbraco.Core.Scoping.IScope.html#Umbraco_Core_Scoping_IScope_Events