Should I be able to base my Azure Function class on Csla.Web.Mvc.Controller? #3003
-
Should I be able to base my Azure Function class on Csla.Web.Mvc.Controller? I have a Blazor client that is using Azure Functions as its API. In this solution I am also using CSLA. Now I am at a point where I want to start using the view model in my blazor client. In my Azure Function I am trying to use the CSLA controller so I can return the business object as with the ViewResult using the Csla.Web.Mvc.Controller. My Framework for the Azure Function project is Microsoft.NETCore.App.Ref\6.0.6. When I build my compile error is CS0012. Error CS0012 The type 'Controller' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. After I added the Csla.Web.Mvc.Controller as the base to my function it wants me to add a reference to Microsoft.AspNetCore.Mvc.ViewFeatures\6.0.0.0 but that assembly is no longer offered from NuGet. I am unable to reference Microsoft.AspNetCore.Mvc.ViewFeatures as an assembly directly. This package was removed as a NuGet. In the Microsoft Q&A I asked why the ViewFeatures assembly is not available in NuGet and someone suggested I should not need it as it was moved to the asp.net core 6 framework. https://docs.microsoft.com/en-us/answers/questions/915139/why-is-there-not-a-microsoftaspnetcoremvcviewfeatu.html?childToView=915215#answer-915215 Some background on my Azure Function evolution. In my first iteration I built the Azure Function project to accept rest calls. When fetching a business object I call my business object portal AnimalEditPortal.FetchAsync(Guid.Parse(id)); My function handles serialization and returns the serialized business object in the OkObjectResult. My blazor client has a service that is then able to deserialize back to a business object. When saving my blazor client service is again handling the serialization and my Azure function is able to deserialize to a business object. This is working great for each of the rest calls. Now I want to use the ViewModel. To use the view model I think I just need to return a ViewResult of the Busines object instead of my own serialization. This is when I added the Csla.Web.Mvc.Controller base to my Azure function class and when I started getting the above error. The following code is my fully functional Azure Function before I attempted to add the base Csla.Web.Mvc.Controller. using Csla;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.Json;
using Arms.Business;
using CPros.IdentityServices.ForServer;
using CPros.IdentityServices.DataAccess;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc;
namespace Arms.AzureFunctions
{
public class FunctionAnimal
{
private const string Route = "animal";
private Csla.ApplicationContext ApplicationContext;
private IDataPortal<AnimalList> AnimalListPortal;
private IDataPortal<AnimalEdit> AnimalEditPortal;
private readonly IConfiguration Configuration; //Needed to Get Token Validation Issuer
public FunctionAnimal(ApplicationContext applicationContext,
IDataPortal<AnimalList> animalListPortal,
IDataPortal<AnimalEdit> personEditPortal,
IConfiguration configuration)
{
ApplicationContext = applicationContext;
AnimalListPortal = animalListPortal;
AnimalEditPortal = personEditPortal;
this.Configuration = configuration;
}
[FunctionName("EntityFramework_GetAnimals")]
public async Task<IActionResult> GetAnimals([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = Route)] HttpRequest req, ILogger log)
{
log.LogInformation($"{Route} 'get' received. Processing EntityFramework_GetAnimals");
if (!ProcessIdentity(req))
{
log.LogWarning("Unable to process identity. Going to return UnauthorizedResult");
return new UnauthorizedResult(); // No authentication info.
}
//var list = await AnimalListPortal.FetchAsync();
//return View(list);
AnimalList animals = await AnimalListPortal.FetchAsync();
var o = Csla.Serialization.SerializationFormatterFactory.GetFormatter(ApplicationContext);
byte[] j = o.Serialize(animals);
return new OkObjectResult(j);
}
[FunctionName("EntityFramework_GetAnimalById")]
public async Task<IActionResult> GetAnimalById(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = Route + "/{id}")] HttpRequest req, ILogger log, string id)
{
log.LogInformation($"{Route} received 'get' with id:{id}. Processing EntityFramework_GetAnimalById");
if (!ProcessIdentity(req))
{
log.LogWarning("Unable to process identity. Going to return UnauthorizedResult");
return new UnauthorizedResult(); // No authentication info.
}
AnimalEdit animal = null;
try
{
animal = await AnimalEditPortal.FetchAsync(Guid.Parse(id));
if (animal == null)
{
log.LogInformation($"Item {id} not found");
return new NotFoundResult();
}
var o = Csla.Serialization.SerializationFormatterFactory.GetFormatter(ApplicationContext);
var byteArray = o.Serialize(animal);
return new OkObjectResult(byteArray);
}
catch (Exception ex)
{
log.LogWarning(ex.Message);
return new NotFoundResult();
}
}
/*
* Create
*
* There is no function to create a new business object as that is handeld at the client
*/
[FunctionName("EntityFramework_UpdateAnimal")]
public async Task<IActionResult> UpdateAnimal(
[HttpTrigger(AuthorizationLevel.Anonymous, "put", Route=Route)] HttpRequest req, ILogger log)
{
/*
* This Update Function Handles both Insert and Update actions. Csla manages that action.
*/
log.LogInformation($"{Route} 'put' received. Processing EntityFramework_UpdateAnimal");
if (!ProcessIdentity(req))
{
log.LogWarning("Unable to process identity. Going to return UnauthorizedResult");
return new UnauthorizedResult(); // No authentication info.
}
// Check if we have authentication info.
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var byteArray = JsonSerializer.Deserialize<byte[]>(requestBody, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
var o = Csla.Serialization.SerializationFormatterFactory.GetFormatter(ApplicationContext);
var animalObject = o.Deserialize(byteArray);
if(animalObject!= null)
{
var animal = (AnimalEdit)animalObject;
if (animal.IsSavable)
{
animal = await animal.SaveAsync();
}
else
{
log.LogError($"Business Object Is Not Savable, Check Broken Rules. {GetUserIdentity()} ");
return new BadRequestObjectResult("Business Object Is Not Savable, Check Broken Rules");
}
byteArray = o.Serialize(animal);
return new OkObjectResult(byteArray);
}
return new BadRequestObjectResult(new DeserializeException("FunctionAnimal was unable to deserialize the animalObject"));
}
[FunctionName("EntityFramework_DeleteAnimal")]
public async Task<IActionResult> DeleteAnimal(
[HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = Route + "/{id}")]
HttpRequest req, ILogger log, string id)
{
log.LogInformation($"{Route} 'delete' received with id:{id}. Processing EntityFramework_DeleteAnimal");
if (!ProcessIdentity(req))
{
log.LogWarning("Unable to process identity. Going to return UnauthorizedResult");
return new UnauthorizedResult(); // No authentication info.
}
var animal = await AnimalEditPortal.FetchAsync(Guid.Parse(id));
if (animal == null)
{
log.LogWarning($"Item {id} not found");
return new NotFoundResult();
}
animal.Delete();
animal = await animal.SaveAsync();
return new OkResult();
}
private bool ProcessIdentity(HttpRequest request)
{
ValidateJWTServer _validatedToken = new ValidateJWTServer(request, Configuration);
if (!_validatedToken.IsValid)
{
return false;
}
ApplicationContext.Principal = _validatedToken.Principal;
return true;
}
private string GetUserIdentity()
{
try
{
var u = ApplicationContext.Principal.FindFirst(CProsClaimTypes.UserName).Value;
var o = ApplicationContext.Principal.FindFirst(CProsClaimTypes.Organization).Value;
return $"{o}-{u}";
}
catch
{
return "GetUserIdentity() Failed";
}
}
}
} Thoughts? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
The Is there any chance the function isn't running under .NET 6? |
Beta Was this translation helpful? Give feedback.
-
My Azure Functions project was based on This appears to be the solution I was after. |
Beta Was this translation helpful? Give feedback.
My Azure Functions project was based on
<Project Sdk="Microsoft.NET.Sdk">
. I updated the Sdk reference to be<Project Sdk="Microsoft.NET.Sdk.Web">
. This added Microsoft.AspNetCore.App.Ref under the dependencies frameworks. Now I can reference Csla.Web.Mvc.Controller.This appears to be the solution I was after.