Can't load controller/routes automatically MVC6 [duplicate] - c#

I have created an WEB API in ASP NET 5 and I can reference an external Class Library vNext.
I am working on Visual Studio 2015 Community.
In that Library I have this controller:
[Route("api/[controller]")]
public class NovosController : Controller
{
// GET: api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "i am", "an external library" };
}
To add this library in my Web API´s references I had to browse the DLL's (one for dnxcore50 and one for dnx451).
This is the result:
dnx451
dnxcore50
In my web API I can get the data from that controller but I can't acess it from URL.
But if the library is in the same Solution I can acess it from the URL.
For example:
If external library:
localhost:51000/api/novos
returns me nothing
but if the library is in the same solution:
localhost:51000/api/novos
returns me " i am an external library"
I want to acess by URL to the external library but I can't find any solution to my problem, there is anyone that knows how to make this thing work?

You don't need anything special to allow your external class library to be discovered by IControllerTypeProvider as long as you comply with the requisites:
has to be class
can’t be abstract
has to be public
has to be top-level (not nested)
can’t be generic
has to either derive from Controller base class or end in Controller suffix (for POCOs) and be located in an assembly that references MVC assembly
(Source)
In your particular case, I think you just need to remove the Route annotation, since it doesn't looks right.
using Microsoft.AspNet.Mvc;
using System.Collections.Generic;
namespace External.Controllers
{
[Route("api/[controller]")]
public class NovosController: Controller
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "I am", "an external library" };
}
}
}

Related

Controller created with .Net source generator is not accessible or visible in Swagger docs

I created a .Net source generator project (.Net 2.0) that creates an Api Controller. The generated controller looks as follows:
using Company.Domain.Enums;
using Company.Domain.Common;
using Company.Api.Authorization;
using Company.Api.Controllers.Core;
using Company.Application.Core.Common.Models;
using Company.Application.Assets.Manufacturer;
using Company.Application.Assets.Manufacturer.Queries.GetManufacturerById;
using Microsoft.AspNetCore.Mvc;
namespace Company.Api.Controllers
{
public partial class ManufacturerController : ApiController
{
[HttpGet("{id}")]
[Produces(typeof(ManufacturerModel))]
public async Task<ActionResult<ManufacturerModel>> GetManufacturerById(int id)
{
ManufacturerModel result = await Mediator.Send(new GetManufacturerByIdQuery { Id = id });
return result != null ? Ok(result) : NotFound();
}
}
}
the ApiController base class takes care of the api decoration as follows:
[Authorize]
[ApiController]
[Route("api/[Controller]/[action]")]
public abstract class ApiController : ControllerBase
{...
My main project is a Dotnet 7.0 Api.
The problem is that this controller does not show up in my swagger documentation (other manually-created endpoints do) and it also gives a 404 when trying to call it with Postman.
It is as if Dotnet does not recognize and register it as a controller.
I tried not using the ApiController base class and just creating it as if it is a standard controller that extends BaseController, although that dit nothing.
Other classes that I create with the source generator function correctly and can be referenced by manually-created Controllers.
I would like to see the Controller added to Swagger and be callable.
I figured it out. Turned out to be an unrelated error in the source generator that was not showing as an exception.

Has anyone had any luck getting a .NET 6 REST API project to work in an AWS Lambda?

I have a very simple ASP.NET 6.0 Web API application, with a Home controller with one Get method returning text:
[ApiController]
[Route("[controller]")]
public class HomeController : Controller
{
// GET
[HttpGet]
public IActionResult Get()
{
return Ok(new { message = "Hello, World!" });
}
}
I've been able to get ASP.NET projects < 6.0 to work, but with .NET 6 I'm running into issues. There's no longer a Startup class; that functionality moved to the implicit Program class. So in my LambdaEntryPoint class (which inherits from APIGatewayProxyFunction) I'm using Program as the Startup:
protected override void Init(IWebHostBuilder builder)
{
builder.UseStartup<Program>();
}
I'm getting an error when manually testing from the AWS console: Amazon.Lambda.RuntimeSupport.ExceptionHandling.LambdaValidationException: Unable to load assembly. I believe that my naming is correct: MyAssembly::MyAssembly.LambdaEntryPoint::FunctionHandlerAsync
The only thing different about my Program class is that I had to add public partial class Program { } at the bottom so the unit tests would could find Program and run.
My Test event looks like this:
{
"resource": "/Home",
"path": "/Home",
"httpMethod": "GET",
"isBase64Encoded": true
}
It is a cut down version of the default Amazon API Gateway AWS Proxy
The fact that you don't have a Startup class doesn't mean you can't make one, I made a Startup class for my API in .NET 6 and it works fine
You do not need to add a Startup.cs class.
The only thing you have to do if you are working with NET6 is in your Program.cs file you have to add this line of code.
This is if you are using a rest API or API GATEWAY
builder.Services.AddAWSLambdaHosting(LambdaEventSource.RestApi);
This is if you are using your lambda with a url
builder.Services.AddAWSLambdaHosting(LambdaEventSource.HttpApi);
..and in aws you just have to change the handler with the name of your project and that's it.
MyAssembly
See the example here in aws

How to share a View Component in a dll-referenced Razor Class Library?

ASP.NET Core 2.2.0
I built a RCL with some (Razor) pages, interfaces, repositories and models and I want to share that RCL using a DLL reference with my other projects. That works fine (using this) and now I want to use the View Components inside the RCL, but it gives me the error:
InvalidOperationException: Unable to resolve service for type 'Shared.ModelInterfaces.IMyRepository' while attempting to activate 'Shared.Components.ItemViewComponent'.
Diving deeper in the error, I found this:
method may only be called on a type for which type.is generic parameter is true
And it looks like this is causing the main error.
My ViewComponent has no Generic Type:
namespace Shared.Components
{
public class ItemViewComponent : ViewComponent
{
private readonly IMyRepository _myRepository;
public ItemViewComponent(IMyRepository myRepository)
{
_myRepository = myRepository;
}
public IViewComponentResult Invoke(string ViewType, string Category = "", string Organization = "", string ItemID = "")
{
// some code / some calls to my _myRepository / some returns
}
}
}
How can I fix this? I need the IMyRepository...
Side note
I know that RCLs usually are referenced by project or as a NuGet Package, but these methods have some disadvantages for me, that's why I reference my RCL by DLL.
You have to register your IMyRepository service in the project using the view component:
services.AddScoped<IMyRespository, MyRepository>();

Base controller from another class library doesn't working in web api

I have two Web API projects and I have a MarketController and I need to extend the Api controller so I did it.
I created a BaseController class and inherit from ApiController like this:
public class BaseController:ApiController { }
so far so good, it's working fine:
public class MarketController : BaseController
{
public MarketController() : base()
{
}
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
But I wanted to do it in another class library called BLL, so I moved the BaseController class to the BLL class library and I referenced it in the Web API project.
When I did this, the api stopped working.
The response is :
{
"Message": "No HTTP resource was found that matches the request URI someurl/api/market.",
"MessageDetail": "No type was found that matches the controller named 'market'."
}
No need to implement custom ControllerFactory or AssemblyResolver classes.
This scenario will "just work" provided you add the Microsoft.AspNet.WebApi.Core nuget package to the assembly containing the base class.
In my case I'd just added a reference to the System.Web.Http.dll which will compile, but the controllers will not load properly. Adding the Nuget package got everything working with no code changes.
By default MVC looks for all controllers in same assembly of mvc application. The default controller factory creates controller instance based on string 'ControllerName+Controller' like MarketController where market comes from url market/actionname.It will look for MarketController in the same assembly as mvc application.
To put controller in separate assembly you will have to create your own controller factory or you will have to specify assembly name is app start.
Once you've created your own custom ControllerFactory, you add the following line to Application_Start in global.asax to tell the framework where to find it:
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
Or for simple cases like yours you can do this :
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" },
new[] { "BLLAssembly.Controllers" }
);
Here BLLAssembly.Controllers is namespace for your BaseController in BLL assembly.
There is one more advanced way using custom assembly resolver ,i.e IAssembliesResolver
The below article tells how to do this with Web Api also,
http://www.strathweb.com/2012/06/using-controllers-from-an-external-assembly-in-asp-net-web-api/

WCF Service reference namespace cannot be found

I've got a local WCF service in my solution which I have referenced. However my controller class is not able to pick up the Service namespace? Traditionally I would use svcUtil to write a wrapper class but as this is internal I though I could simply add 'Service Reference', tap into the namespace then simple invoke my service (ie var service = new QServiceReference.MyClass();)
I'm unable to show pictures so here's the structure for my solution,
Solution
-> Services Folder
-> QService Folder
QService Project
-> Web Folder
-> Zipporah.Queuing.Web (project)
-> Services References
-> QServiceReference
-> Controllers Folder
-> KioskProcessController
My class (KioskProcessController) is as follows:
using System.Web.Mvc;
using Zipporah.Queuing.Web.QServiceReference; (ITS THIS NAMESPACE REFERENCE THAT DOES NOT WORK)
namespace Zipporah.Queuing.Web.Controllers
{
public class KioskProcessController : ZipController
{
public ActionResult Index()
{
return View();
}
public ViewResult Queue()
{
return View();
}
public ViewResult PreAppointment()
{
return View();
}
}
}
Sorry if that structure is not clear (as aforementioned i cannot post pictures)
Any clues or thoughts would be most appreciated?
The namespace generated for your WCF Client might be different than the one you are using. In your Solution Explorer window, when you select your Service References folder, you can enable the Show All Files button and then navigate to file Reference.cs as shown in below screenshot:
Then, in Reference.cs file, you can find the actual generated namespace by the Add Service Reference dialog, which you can use in your other file with a using statement.

Categories

Resources