Put, Delete... Method not allowed in Orchard - asp.net-web-api

I've created WebApi controller based on following tutorial: sebastienros website
My modules name is Company.Accounts.
public class AccountController : ApiController
{
[HttpPost]
public string LogIn([FromBody] UserModel user)
{
// this is working
return this.accountService.LogIn(user.UserName, user.Password);
}
[HttpPut]
public string SomePuthMethod([FromBody] UserModel user)
{
// method not allowed
// some code...
}
}
Implementation of IHttpRouteProvider looks like:
private IEnumerable<RouteDescriptor> GetAccountRoute()
{
yield return new HttpRouteDescriptor
{
Name = "Account",
Priority = 10,
RouteTemplate = "Api/Account",
Defaults = new
{
area = "Company.Accounts",
controller = "Account"
}
};
}
Unfortunately, everything except GET and POST *is not working*. I'm getting simple
Method not allowed.
What's wrong? My Orchard version is 1.7.1.

You put them in the MethodNames public HttpResponseMessage Post([FromBody]...){}

Related

Conditional validation based on request route with asp.net core 2.2 and FluentValidation

So Basically i wrote a validator for my class with FluentValidation and also a filter to do the validation task for me in my webAPI project, so far it's OK but assume that my User class has firstname,lastname,email,password properties
and i have two routes (one for register and the other one for login)
and as you might have noticed required properties are different on these route.
Thus,should I really need to write individual validation for each and every action i have?because this makes a lot of code code duplication and it's hard to change.is there any way to just add required condition based on the request coming with single validation class?
Any suggestion???
A better practice would be to use a factory pattern for your validations and use a an action filter to short circuit bad requests. You could validate any action argument(Headers, Request Bodies, etc..) with something like this.
public class TestValidationAttribute : Attribute, IActionFilter
{
private string _requestModelName;
public TestValidationAttribute(string requestModelName)
{
_requestModelName = requestModelName;
}
public void OnActionExecuting(ActionExecutingContext context)
{
// using Microsoft.Extensions.DependencyInjection;
var services = context.HttpContext.RequestServices;
var accessor = services.GetService<IHttpContextAccessor>();
var factory = services.GetService<ITestValidatorFactory>();
var tokens = accessor.HttpContext.GetRouteData().DataTokens;
if (!tokens.TryGetValue("RouteName", out var routeNameObj))
{
throw new Exception($"Action doesn't have a named route.");
}
var routeName = routeNameObj.ToString();
var validator = factory.Create(routeName);
if (!context.ActionArguments.TryGetValue(_requestModelName, out var model))
{
throw new Exception($"Action doesn't have argument named {_requestModelName}.");
}
TestModel test;
try
{
test = (TestModel) model;
}
catch (InvalidCastException)
{
throw new Exception($"Action argument can't be casted to {nameof(TestModel)}.");
}
var validation = validator.Validate(test);
if (!validation.Successful)
{
context.Result = new BadRequestObjectResult(validation.ResponseModel);
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
}
public class TestController : Controller
{
[HttpPost]
[Route("Test/{id}", Name = "TestGet")]
[TestValidation("model")]
public IActionResult Test(TestModel model)
{
return Ok();
}
}
public class ValidationResult
{
public bool Successful { get; }
public ResponseModel ResponseModel { get; }
}
public class TestModel
{
}
public interface ITestValidator
{
ValidationResult Validate(TestModel model);
}
public interface ITestValidatorFactory
{
ITestValidator Create(string routeName);
}

How to call a custom identity Register method from a controller in .net core 2.1 mvc

I want to use custom register identity method that is called in a controller to Register users automatically with a corresponding role. Here the code that I found so far:
public class RegisterUsers
{
private readonly UserManager<ApplicationUser> _userManager;
public RegisterUsers(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
public async Task SystmRegisterUsers(string uname, string sysid, string Email)
{
var newuser = new ApplicationUser
{
UserName = uname,
Email = Email,
SystemuserID = sysid
};
string UserPassword = PasswordGenerator.Generate(6, 3, true, true, true, true);
//var _user = await UserManager.FindByEmailAsync(Configuration.GetSection("UserSettings")["UserEmail"]);
var createParentUser = await _userManager.CreateAsync(newuser, UserPassword);
if (createParentUser.Succeeded)
{
//here we tie the new user to the "Admin" role
await _userManager.AddToRoleAsync(newuser, "Parent");
}
}
}
And I want to call the method SystmRegisterUsers like this in a controller
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("fullname,id,email,...")]MyModel parent)
{
if (ModelState.IsValid)
{
//create new records
_context.Add(parent);
await _context.SaveChangesAsync();
// and i want to call the method here to create identity users using the data entered:
var instance = new RegisterUsers();
await instance.SystmRegisterUsers(parent.FullName, parent.Parentid, parent.Parentid);
}
return View(parent);
}
And it is saying I’m missing an argument that is corresponds to userManager . I don’t even know if it is the right way to do what I want to do, I think I’m missing some basic thing please help!
For RegisterUsers, it needs UserManager<ApplicationUser> userManager, for resolving the RegisterUsers from Dependency Injection, you could follow steps below:
Register RegisterUsers in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
//your rest code
services.AddScoped<RegisterUsers>();
}
Initialize RegisterUsers by Dependency Injection
public class HomeController : Controller
{
private readonly RegisterUsers _registerUsers;
public HomeController(RegisterUsers registerUsers)
{
_registerUsers = registerUsers;
}
public async Task<IActionResult> Index()
{
await _registerUsers.SystmRegisterUsers("a1", "b1", "c1");
return View();
}

WebApi: method to return a simple string

One of my methods need to return just a simple string of text. What should be the return type of the method? Do I still declare it in a subclass of ApiController?
I tried the following but it does not work:
public class TestController : ApiController
{
public string Announcements()
{
return "Testing abc";
}
}
By default, Web API will send the string as a JSON. However, you can manually force it to return just the text itself and accompany it with the appropriate content type:
public class TestController : ApiController
{
public HttpResponseMessage Announcements()
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StringContent("Testing abc");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
return response;
}
}

WebAPI 2.0 Multiple Get on single controller

I'm currently trying to implement a simple WebAPI 2.0 controller to get and retrieve users from a central table.
Looking at implementing :
GetUserByName(string userName)
GetUserByID(int userId)
GetUserByEmail(string email)
Using Routing I have been able to get the api to work with GetById and GetByName. I have also added a route prefix to the controller level
The code looks like this so far, There isn't very much being done in the API controller at the moment I just wish to test that the correct methods are being hit.
[RoutePrefix("api/user")]
public class UserController : ApiController
{
[Route("")]
[HttpGet]
public IEnumerable<User> Get()
{
return new List<User>();
}
// GET: api/Users/5
[Route("{id:int}")]
public User Get(int id)
{
return new User();
}
[Route("{id}/PasswordHash")]
[HttpGet]
public string PasswordHash(int id)
{
return "test";
}
[Route(Name = "/{userName:alpha}")]
public User GetByName(string userName)
{
return new User();
}
[Route(Name = "/GetByEmail/{email}")]
[HttpGet]
public User GetByEmail(string email)
{
return new User()
}
// POST api/<controller>
[HttpPost]
[Route("")]
public string Post([FromBody]User value)
{
return "test";
}
}
Once I add in the get by email it doesn't seem to work, I've tried giving the method it's own custom routing but unfortunately it doesn't seem to work. Any suggestions would be great.
You have set the name of the routes not the routes themselves, and since both methods have the same signature with one string variable you get the problem, so change your code to be :
[Route("/{userName:alpha}")]
public User GetByName(string userName)
{
return new User();
}
[Route("/GetByEmail/{email}")]
[HttpGet]
public User GetByEmail(string email)
{
return new User()
}
hope this helps.

UserManager in ApiController

In my project HttpContext is a member of Controller and I can use it in AccountController : Controller. But I can't access an information about current user in ApiController in contraction like
public class AccountController : ApiController
{
public UserManager<ApplicationUser> UserManager { get; private set; }
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.Current.GetOwinContext().Authentication;
}
}
}
So how to write custom ApiController right?
In the method below user variable shows me null on breakpoint. How can I retrive current user if I know that hi is logined?
public IHttpActionResult GetUser(int id)
{
var manager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
var userid = User.Identity.GetUserId();
var user = manager.FindById(userid);
var data = new Person {Name = user.UserName, Age = 99};
return Ok(data);
}
From within any controller method you can do this.GetRequestContext().User to get the currently authenticated user. The static HttpContext.Current is not supported by WebApi.
manager.FindById(userid) retrieves a user from the database as opposed to the current . To get the current user, simply access the User property within your ApiController:
public class MyApiController : ApiController
{
IPrincipal GetCurrentUser(){
return User;
}
}
This may help you:
protected string UserId { get { return User.Identity.GetUserId(); } }

Resources