Добавление дочерней сущности работает локально, но не на действующем сайте Azure. - PullRequest
0 голосов
/ 20 марта 2019

У меня есть действие контроллера веб-приложения, которое создает дочернюю сущность. У меня есть модель Location с коллекцией LocationPic. Я пытаюсь добавить новый LocationPic к существующему Location. Локально это работает нормально, но когда я запускаю его в Azure, создается LocationPic, но не ссылается на Location. Таким образом, я получаю осиротевший LocationPic, который не знает, к какому местоположению он принадлежит.

Кроме того, он отлично работает локально и в Azure для местоположений, которые УЖЕ имеют фотографии (у меня есть отдельный контроллер API, который, кажется, работает нормально). Так что я могу добавить новые картинки в локации, которые уже есть. Но я не могу добавить новые фотографии в новое место, где нет фотографий.

Вот мое действие контроллера:

// POST: Pictures/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("LocationID,Name,Description")] LocationPic locationPic, IFormFile image)
{
    var location = await _context.Locations.FindAsync(locationPic.LocationID);
    if (location == null)
    {
        return NotFound();
    }

    Trace.TraceInformation($"Create Pic for location[{location.LocationID}:{location.LocationName}]");

    _userService = new UserService((ClaimsIdentity)User.Identity, _context);
    if (!_userService.IsAdmin)
    {
        return Unauthorized();
    }

    if (image == null)
    {
        return BadRequest();
    }

    if (String.IsNullOrEmpty(locationPic.Name))
    {
        locationPic.Name = image.FileName;
    }

    var helper = new AzureTools();
    var filename = await helper.GetFileName(image);

    locationPic.FileName = filename;

    //Added this to try to force LocationPics to be initialized
    if (location.LocationPics == null)
    {
        Trace.TraceInformation("location.LocationPics is null");
        location.LocationPics = new List<LocationPic>();
    }
    else
    {
        Trace.TraceInformation($"location.LocationPics count == {location.LocationPics.Count}");
    }

    if (ModelState.IsValid)
    {
        Trace.TraceInformation($"Location pic valid: [{locationPic.LocationID}] {locationPic.Name}");
        //Overly-explicit attempts to get entities linked
        locationPic.Location = location;
        location.LocationPics.Add(locationPic);
        //I've tried _context.LocationPics.Add as well and seemingly no difference
        _context.Add(locationPic);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Edit), new { locationID = location.LocationID });
    } else
    {
        Trace.TraceInformation("Invalid model state");
        return BadRequest();
    }
}

Кажется, вся правильная информация входит в мои параметры из моей формы, и LocationPic создается отлично. Он просто не связан с Location, несмотря на то, что «LocationID» отображается правильно перед сохранением. Кроме того, я получаю правильное перенаправление назад к действию «Редактировать», а не к «БадРеквесту» или чему-либо еще.

Локально, единственное отличие, которое я заметил, состоит в том, что у Location без картинок есть LocationPics, который является пустой коллекцией с Count == 0. В Azure для местоположения без изображений, как представляется, значение LocationPics имеет значение null. Вот почему я попытался добавить бит, который инициализирует его, если он нулевой, хотя мой работающий контроллер API не должен был делать ничего подобного.

Вот мое (работающее) действие API Controller, для справки:

[HttpPost("{id}", Name = "PostPicture")]
public async Task<IActionResult> PostPicture([FromRoute] int id, IFormFile image, string Name, string Description)
{
    var location = _context.Locations.Find(id);
    if (location == null)
    {
        return NotFound();
    }

    _userService = new UserService((ClaimsIdentity)User.Identity, _context);
    if (!_userService.IsCustomer(location.CustomerID))
    {
        return Unauthorized();
    }

    if (image == null)
    {
        return BadRequest();
    }

    if (String.IsNullOrEmpty(Name))
    {
        Name = image.FileName;
    }

    var helper = new AzureTools();
    var filename = await helper.GetFileName(image);

    var locationPic = new LocationPic
    {
        Name = Name,
        FileName = filename,
        Description = Description,
        Location = location
    };

    _context.LocationPics.Add(locationPic);
    _context.SaveChanges();
    return Ok(filename);
}

1 Ответ

0 голосов
/ 21 марта 2019

Оказывается, что фотографии местоположения шли хорошо, но в моих действиях контроллера, которые я отображал, я не использовал .Include (), чтобы включить коллекцию LocationPics? За исключением того, что это сработало для локаций, у которых ранее были фотографии локаций? И это работало на месте совершенно нормально для всего. Так что я не совсем уверен.

Как только я добавлю .Include (), чтобы включить коллекцию LocationPics в мое действие контроллера "EditByLocation", которое захватывает местоположение по идентификатору и отправляет его в представление, отображающее местоположение и фотографии для этого местоположения, все предыдущие фотографии. Я добавил появившиеся в поле зрения места, которые, как мне казалось, не получали их. По какой-то причине, Местоположение A (с фотографиями) отображало свои фотографии нормально, но Расположение B (очевидно, с фотографиями, но я не мог видеть их до сих пор) не отображало их. У меня не было причин полагать, что местоположения отображались некорректно, потому что некоторые отображались нормально, а другие пришли с нулевой коллекцией LocationPics. Так что это не имеет смысла для меня. Но, похоже, сейчас работает.

Для полноты, вот мой последний код действия контроллера, который, как вы можете заметить, очень похож на действие контроллера API, с которого он выглядел, начиная с:

// POST: Pictures/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("LocationID,Name,Description")] LocationPic locationPic, IFormFile image)
{
    var location = await _context.Locations.FindAsync(locationPic.LocationID);
    if (location == null)
    {
        return NotFound();
    }

    _userService = new UserService((ClaimsIdentity)User.Identity, _context);
    if (!_userService.IsAdmin)
    {
        return Unauthorized();
    }

    if (image == null)
    {
        return BadRequest();
    }

    if (String.IsNullOrEmpty(locationPic.Name))
    {
        locationPic.Name = image.FileName;
    }

    var helper = new AzureTools();
    var filename = await helper.GetFileName(image);

    locationPic.FileName = filename;

    if (ModelState.IsValid)
    {
        locationPic.Location = location;
        _context.LocationPics.Add(locationPic);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(EditByLocation), new { locationID = location.LocationID });
    }             

    return View("EditByLocation", location);
}

А вот мое новое действие контроллера EditByLocation:

// GET: Pictures/EditByLocation?locationID=5
public async Task<IActionResult> EditByLocation(int locationID)
{
    _userService = new UserService((ClaimsIdentity)User.Identity, _context);
    if (!_userService.IsAdmin)
    {
        return Unauthorized();
    }

    ViewData["ImageBaseUrl"] = _config["AzureStorage:Url"] + "/" + _config["AzureStorage:Folder"];

    var location = await _context.Locations.Include(l => l.LocationPics).FirstOrDefaultAsync(l => l.LocationID == locationID);

    if (location == null)
    {
        return NotFound();
    }

    if (location.LocationPics == null)
    {
        location.LocationPics = new List<LocationPic>();
    }

    return View("EditByLocation", location);
}

Единственным реальным изменением выше было добавление .Include (l => l.LocationPics). Итак, опять же, не знаю, почему это работало локально без него, и почему НЕКОТОРЫЕ местоположения работали в Azure без него, но не другие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...