public async Task <IActionResult> Edit(int id, [Bind("CritterImageId,Data")] CritterImage val) { if (val.CritterImageId != id) { return(NotFound()); } this.FixNullFields(val); if (ModelState.IsValid) { try { _context.Update(val); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!Exists(val.CritterImageId)) { return(NotFound()); } else { throw; } } return(RedirectToAction(nameof(Index))); } return(View(val)); }
public async Task <IActionResult> Create([Bind("CritterImageId,Data")] CritterImage val) { this.FixNullFields(val); if (ModelState.IsValid) { _context.Add(val); await _context.SaveChangesAsync(); return(RedirectToAction(nameof(Index))); } return(View(val)); }
public void RegisterCritter(Critter critter) { critters.Add(critter); if (critters.Count - 1 < critterColours.Length) { critter.SetColour(critterColours[critters.Count - 1]); } critter.id = critters.Count - 1; critterImages.Add(new RenderTexture(256, 256, 16)); CritterImage newImage = Instantiate(critterImagePrefab, new Vector3((critter.id + 1) * 1000, 0, 0), Quaternion.identity); newImage.SetupImage(critterColours[critter.id], critterImages[critter.id]); }
private void FixNullFields(CritterImage val) { }
public async Task <IActionResult> Image(int critterId, int cacheVersion, int?width, int?height, CancellationToken cancelToken) { // Limit to only processing a certain amount of image requests, to prevent the rest of the // website from dying when someone needs to get a lot of images. while (Interlocked.Read(ref _imageRequestCounter) >= MAX_IMAGE_SIMUL_REQUESTS) { await Task.Delay(IMAGE_DELAY_MS); cancelToken.ThrowIfCancellationRequested(); } try { Interlocked.Increment(ref _imageRequestCounter); var critter = await this._livestock.Critter.FirstAsync(c => c.CritterId == critterId); // If the critter has an image, retrieve it. if (critter.CritterImageId != null) { CritterImage image = null; // If we need a specific size, either retrieve or create it. if (width != null && height != null) { // Prevent exploits if (width > MAX_IMAGE_RESIZE_WIDTH || height > MAX_IMAGE_RESIZE_HEIGHT) { return(BadRequest("Width or height was too high.")); } if (width < 0 || height < 0) { return(BadRequest("Width or height cannot be negative.")); } var variant = await this._livestock.CritterImageVariant .FirstOrDefaultAsync(v => v.CritterImageOriginalId == critter.CritterImageId && v.Width == width && v.Height == height); if (variant != null) { return(await this.GetAndCacheImage(critter, variant.CritterImageModifiedId, cacheVersion, width, height)); } else { variant = new CritterImageVariant { CritterImageOriginalId = critter.CritterImageId.Value, Width = width.Value, Height = height.Value }; await this._livestock.Entry(critter).Reference(c => c.CritterImage).LoadAsync(); image = critter.CritterImage; // Resize it, then upload it so it's cached. var resized = await this.ResizeImageAsyncPOOLED(image.Data, width.Value, height.Value); image = new CritterImage { Data = resized }; variant.CritterImageModified = image; try { await this._livestock.CritterImage.AddAsync(image); await this._livestock.CritterImageVariant.AddAsync(variant); await this._livestock.SaveChangesAsync(); } finally // I can count on one hand the amount of times I've used 'finally'. { // We detach the entity, since the image data shouldn't be reference anymore once it's returned. // And if we set it to 'null', then we can accidentally remove the image data if we save at some point. // So it's safer to just detach it, and take the performance hit of downloading a new version of it when needed. this._livestock.Entry(image).State = EntityState.Detached; _imageBufferPool.Return(resized); } return(File(image.Data, "image/png")); } } else // Otherwise, return the original. { return(await this.GetAndCacheImage(critter, critter.CritterImageId.Value, cacheVersion, width, height)); } } else { return(Redirect("/images/icons/default.png")); } } finally { Interlocked.Decrement(ref _imageRequestCounter); } }