ServiceStack JsonServiceClient: The requested resource does not support http method GET - http

So I recently remade my API and client in a new solution on a different version control scheme. Some of the code has change, but nothing related to the JsonServiceClient. Anyways, I'm getting this exception stating 405 Method Not Allowed Code: Method Not Allowed, Message: The requested resource does not support http method 'GET'.
The issue is that the request is not a GET but a POST, I'm not sure where its getting mixed up. The actual post is represented as such:
var result = (
await
webService.PostAsync(new Login
{
Token = token,
Provider = provider,
IsLinkedAccount = isLinkedAccount,
ResponseText = responseText,
Uuid = uuid,
Platform = platform
}))
The Login DTO is represented as this:
[Route("/login", "POST")]
public partial class Login
: IReturn<LoginDTO>
{
public virtual string Token { get; set; }
public virtual SocialNetworks Provider { get; set; }
public virtual string Email { get; set; }
public virtual bool IsLinkedAccount { get; set; }
public virtual string ResponseText { get; set; }
public virtual string Uuid { get; set; }
public virtual Platform Platform { get; set; }
}
And the actual API route is represented as this:
public class LoginController : ApiController
{
[AcceptVerbs("POST")]
public async Task<LoginDTO> Login(Login request)
{
...
}
}
And I've used swagger and postman to verify that the endpoint is indeed accurate and I can manually send an HTTP POST, so what messed up with the JsonServiceClient?
These is the service stack versions I'm using
<package id="ServiceStack.Client" version="4.0.52" targetFramework="net452"/>
<package id="ServiceStack.Common" version="4.0.52" targetFramework="net452"/>
<package id="ServiceStack.Interfaces" version="4.0.52" targetFramework="net452" />
<package id="ServiceStack.Text" version="4.0.52" targetFramework="net452" />

Related

Xamarin Refit type initializer for System.Text.Json.JsonSerializer threw an exception

I am using Refit 6.1.15 in a Xamarin forms project. My code works exactly as expected on Android, but on iOS, I get a "The type initializer for 'System.Text.Json.JsonSerializer' threw an exception." when I execute my api.
I am using Microsoft.Extensions for DI - my configuration of my service in my Startup.cs class looks like this:
services.AddRefitClient<IAuthorizeApi>()
.ConfigureHttpClient(c => c.BaseAddress = new Uri(BaseAddress))
.AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(15)
}));
My IAuthorizeAPI looks like this:
using System;
using System.Threading.Tasks;
using CivicMobile.Models;
namespace CivicMobile.Services
{
public interface IAuthorizeApi
{
[Post("/v1/DataStage/UserAuthentication/Authenticate?companyCode={queryParms.companyCode}&username={queryParms.username}&password={queryParms.password}&deviceIdentifier={queryParms.deviceIdentifier}")]
[QueryUriFormat(UriFormat.Unescaped)]
Task<ApiResponse<AuthResponse>> Login(Authorize queryParms);
}
My call that throws the error (in my ViewModel) is:
var authToken = await _authenticateService.Login(queryParms);
The return value for the Login (wrapped in ApiResponse) looks like this:
namespace CivicMobile.Models
{
public class AuthResponse
{
[AliasAs("access_token")]
public string AccessToken { get; set; }
[AliasAs("token_type")]
public string TokenType { get; set; }
[AliasAs("expires_in")]
public int ExpiresIn { get; set; }
[AliasAs("userName")]
public string Username { get; set; }
[AliasAs("userIdentifier")]
public string UserIdentifier { get; set; }
[AliasAs(".issued")]
public string IssuedAt { get; set; }
[AliasAs(".expires")]
public string ExpiresAt { get; set; }
}
I have replaced [AliasAs()] with [JsonPropertyName()] but the results are the same.
This error ONLY occurs on iOS - not on Android. Any suggestions?
Add the following code in your iOS(.csproj ):
<ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.4">
<IncludeAssets>none</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Buffers" Version="4.5.1">
< IncludeAssets>none</IncludeAssets>
</PackageReference>
</ItemGroup>
I took refit out of my DI Container and the problem went away entirely. No other changes in my code at all. I will try another DI system as I prefer to use DI in this app and refit.
Another update - I had AddHttpClient as well as the AddRefitClient in my ConfigureServices method. It was actually dead code (as I migrated to Refit but never got rid of dead code). That caused my POST to return a proper ApiResponse object with Content that was deserialized properly. So back to what I had planned in the beginning - thanks for your suggestion - it was helpful on another issue (a very large dataset returning - different Api).

asp.net web api: only during sql connection - HTTP 500 Error occurs : Local host is currently unable to handle request

The Web Api throws HTTP 500 error when it has to reference values from sql database.
https://localhost:44304/api/values
This works fine.
But,
https://localhost:44304/api/User
throws HTTP 500 Error - Local host is currently unable to handle request
The API is a simple test one, which has to retrieve data from User table in SQL database.
private readonly string connectionString =
"Server=MyServerName\\SQLEXPRESS;Database=MyDatabase;Trusted_Connection=True;user
id=dbuser;password=dbuserpass;";
The data access file:
namespace UserLogin.Models
{
public partial class User
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
}
No changes being done to any portions of the default code after creating the Web API Component.
Note: using udl, the test connection to the database was successful.
Thanks for help.

.NET Core OData Action Parameter Null

My Odata Action Parameters are not resolving / deserializing.
I am using dotnet core 2.2 to surface an OData controller.
I need to implement an unbounded action. The action parameter (UserDto userDto) is not being deserialized by the OData routing engine:
[AllowAnonymous]
[HttpPost]
[ODataRoute(Routing.Endpoints.UserRoutes.AUTHENTICATE)]
public async Task<IActionResult> Authenticate(UserDto userDto)
{
var user = await _userService.Authenticate(userDto?.Username, userDto?.Password);
if (user == null)
return BadRequest("Username or password is incorrect");
var dto = Mapper.Map<UserDto>(user);
return Ok(dto);
}
Here is my configuration:
app.UseMvc(routeBuilder =>
{
var odataBuilder = new ODataConventionModelBuilder(app.ApplicationServices);
odataBuilder.EnableLowerCamelCase();
odataBuilder.EntitySet<BookDto>(nameof(Book));
odataBuilder.EntitySet<UserDto>(nameof(User));
var authenticate = odataBuilder.Action(Routing.Endpoints.UserRoutes.AUTHENTICATE);
authenticate.Parameter<UserDto>("userDto");
routeBuilder.Select().Expand().Filter().OrderBy().Count().MaxTop(int.MaxValue);
routeBuilder.MapODataServiceRoute("odata", string.Empty, odataBuilder.GetEdmModel());
});
Here is the UserDto:
public class UserDto
{
[Key] public Guid Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Token { get; set; }
}
When I post:
The action is resolved by the routing engine - but the parameter does not have the "Username" and "Password" values:
If I use the [FromBody] attribute on the parameter - the "userDto" parameter is null:
The schema seems correct:
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Default">
<Action Name="authenticate">
<Parameter Name="userDto" Type="ExampleApi.Dto.UserDto"/>
</Action>
<EntityContainer Name="Container">
<EntitySet Name="Book" EntityType="ExampleApi.Dto.BookDto"/>
<EntitySet Name="User" EntityType="ExampleApi.Dto.UserDto"/>
<ActionImport Name="authenticate" Action="Default.authenticate"/>
</EntityContainer>
</Schema>
I have tried following this: Action Parameter Support
And even Microsofts version (albeit dated): Actions and Functions in OData
Been banging my head on this all day...
You could use simple WebApi attributes only to achieve authentication
public class UserController : ODataController
{
[AllowAnonymous]
[HttpPost("user/auth")]
public async Task<IActionResult> Authenticate([FromBody] UserDto userDto)
{
return Ok(userDto);
}
}

Getting The connection to localhost was interrupted. When trying to send a JSON representation of a [DataContract] marked object

I am using the following method to send a JSON representation of a List of a custom object through a WCF service hosted on my local machine:
[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
public List<MyObject> GetObjects()
{
return MyObject.GetObjects();
}
The class MyObject is marked with the [DataContract] attribute, When I request the method using Rest URL, I get the error
This webpage is not available, The connection to localhost was interrupted.
When I remove the [DataContract] atribute, it works fine. I read many articles that you should enable SSL and configure the service behavior to set the certificate name and store and that sort of stuff, but isthis the right and only way to make it work? Shouldn't it be straighforward?
The code for MyObject is :
[DataContract]
public class MyObject
{
[DataMember]
public int ID { get ; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
}
Make sure that all the properties marked as [DataMember] have get and set, that is they are not readonly, not sure why but I once faced this issus and solved it like this.

ASP.NET Web API - Entity Framework - 500 Internal Server Error On .Include(param => param.field)

I am currently working on a Web API project with a Database-First method using Entity Framework (which I know is not the most stable of platforms yet), but I am running into something very strange.
When the GET method within my APIController tries to return all records in a DbSet with a LINQ Include() method involved such as this, it will return a 500 error:
// GET api/Casinos
public IEnumerable<casino> Getcasinos()
{
var casinos = db.casinos.Include(c => c.city).Include(c => c.state);
return casinos.AsEnumerable();
}
Yet, this method works fine, and returns my data from within my database:
// GET api/States
public IEnumerable<state> Getstates()
{
return db.states.AsEnumerable();
}
So I have proved in other instances that if it returns the entities without LINQ queries, it works great, yet when there is an Include method used upon the DbContext, it fails.
Of course, trying to find this error is impossible, even with Fiddler, Chrome/Firefox dev tools, and adding in GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
If anyone has resolved this, it would be nice to know a nice resolution so I can start returning my data! Thanks!:)
P.S. I am using SQL Server 2012
This is happening due to error in serialization (Json/XML). The problem is you are directly trying to transmit your Models over the wire. As an example, see this:
public class Casino
{
public int ID { get; set; }
public string Name { get; set; }
public virtual City City { get; set; }
}
public class State
{
public int ID { get; set; }
public string Name { get; set; }
[XmlIgnore]
[IgnoreDataMember]
public virtual ICollection<City> Cities { get; set; }
}
public class City
{
public int ID { get; set; }
public string Name { get; set; }
public virtual State State { get; set; }
[XmlIgnore]
[IgnoreDataMember]
public virtual ICollection<Casino> Casinos { get; set; }
}
public class Context : DbContext
{
public Context()
: base("Casino")
{
}
public DbSet<Casino> Casinos { get; set; }
public DbSet<State> States { get; set; }
public DbSet<City> Cities { get; set; }
}
Pay attention to the XmlIgnore and IgnoreDataMember. You need to restrict avoiding serialization so it doesn't happen in circular manner. Further, the above model will still not work because it has virtual. Remove virtual from everywhere namely City, Cities, Casinos and State and then it would work but that would be inefficient.
To sum up: Use DTOs and only send data that you really want to send instead of directly sending your models.
Hope this helps!
I had same problem in ASP.Net Core Web Api and made it working with this solution:
Add Microsoft.AspNetCore.Mvc.NewtonsoftJson nuget package to web api project.
and in Startup.cs class in ConfigureServices method add this code:
services.AddControllersWithViews().AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);

Resources