Related
I have some integration tests that use a real database targetting a ConfigurationDbContext. When upgrading to Duende IdentityServer 6.0, the constructor for ConfigurationDbContext breaks (only accepts 1 arg instead of 2) because of the DbContext connection pooling feature that was added.
This code breaks:
public static ConfigurationDbContext GetConfigurationDbContext()
{
var connectionString = Configuration.GetConnectionString("ConfigurationDbContext");
var builder = new DbContextOptionsBuilder<ConfigurationDbContext>();
builder.UseSqlServer(connectionString);
var options = new ConfigurationStoreOptions
{
DefaultSchema = Schema.IdSrv
};
return new ConfigurationDbContext(builder.Options, options);
}
So I changed it to:
return new ConfigurationDbContext(builder.Options);
Now I can build, but my tests fail with this error:
Unable to resolve service for type 'Duende.IdentityServer.EntityFramework.Options.ConfigurationStoreOptions'
How am I supposed to pass the ConfigurationStoreOptions in? Looking at the code in Github, it looks like it relies on dependency injection. (Getting the options from services collection).
OK, I figured out my own problem, but I had to hunt and peck around. It is not listed as a breaking change in the upgrade documentation:
https://docs.duendesoftware.com/identityserver/v6/upgrades/v5.2_to_v6.0/
The solution is to upgrade your project to 6.1
<PackageReference Include="Duende.IdentityServer.EntityFramework.Storage" Version="6.1.5" />
Then you can use this code instead (StoreOptions has been made a public set property)
public static ConfigurationDbContext GetConfigurationDbContext()
{
var connectionString = Configuration.GetConnectionString("MyIdentity");
var builder = new DbContextOptionsBuilder<ConfigurationDbContext>();
builder.UseSqlServer(connectionString);
var options = new ConfigurationStoreOptions
{
DefaultSchema = Schema.IdSrv
};
var dbContext = new ConfigurationDbContext(builder.Options);
dbContext.StoreOptions = options;
return dbContext;
}
This will work for ConfigurationDbContext and PersistedGrantDbContext.
I'm trying to make a simple API call from a .NET Core MVC application:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:49897");
var response = client.GetAsync("some-route").Result;
var dataString = response.Content.ReadAsStringAsync().Result; // Unexpected data here. See below.
[...] // deserialize dataString
}
client.GetAsync(route) successfully hits an API action method, which ultimately does this:
public HttpResponseMessage Get([FromUri] BindingModel bindingModel)
{
List<SomeModel> resultObjects;
[...] // populate resultObjects with data
return Request.CreateResponse(HttpStatusCode.OK, resultObjects, new JsonMediaTypeFormatter());
}
But dataString ends up equaling this:
"{\"version\":{\"major\":1,\"minor\":1,\"build\":-1,\"revision\":-1,\"majorRevision\":-1,\"minorRevision\":-1},\"content\":{\"objectType\":\"System.Object, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e\",\"formatter\":{\"indent\":false,\"serializerSettings\":{\"referenceLoopHandling\":0,\"missingMemberHandling\":0,\"objectCreationHandling\":0,\"nullValueHandling\":0,\"defaultValueHandling\":0,\"converters\":[],\"preserveReferencesHandling\":0,\"typeNameHandling\":0,\"metadataPropertyHandling\":0,\"typeNameAssemblyFormat\":0,\"typeNameAssemblyFormatHandling\":0,\"constructorHandling\":0,\"contractResolver\":null,\"equalityComparer\":null,\"referenceResolver\":null,\"referenceResolverProvider\":null,\"traceWriter\":null,\"binder\":null,\"serializationBinder\":null,\"error\":null,\"context\":{},\"dateFormatString\":\"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK\",\"maxDepth\":null,\"formatting\":0,\"dateFormatHandling\":0,\"dateTimeZoneHandling\":3,\"dateParseHandling\":1,\"floatFormatHandling\":0,\"floatParseHandling\":0,\"stringEscapeHandling\":0,\"culture\":{}}}}}"
Or, in JSON format:
{
version: {
major: 1,
minor: 1,
[...]
},
content: {
objectType: "System.Object, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
formatter: {
indent: false,
serializerSettings: {
[...]
}
}
}
}
My list of models isn't in there at all.
What exactly is being returned, and why isn't my list of models in the response? I've looked at several online resources, and I seem to be doing things the same way as they show. This is a pretty bread-and-butter API call, so I'm not sure what's going on.
What exactly is being returned, and why isn't my list of models in the response?
What's being returned is a JSON-serialized version of your HttpResponseMessage, because while Web API 2 handles this type specially, ASP.NET Core web API does not.
To be precise, ASP.NET Core web API supports returning the following types:
IActionResult
ActionResult<T>
<any other type>
The first two are treated specially, but the third results in that type being JSON-serialized and returned, exactly as you saw.
In contrast, Web API 2 supports the following special return types:
void
HttpResponseMessage
IHttpActionResult
<any other type>
The correct solution is to update your code to use a custom IActionResult implementation instead of returning raw HttpResponseMessages. You may find this guide aids you in doing so - in particular, the Microsoft.AspNetCore.Mvc.WebApiCompatShim NuGet package has a ResponseMessageResult class that allows you to convert your Web API controller method from this:
public HttpResponseMessage Foo(Bar quux)
{
return new BazHttpResponseMessage();
}
to this:
public IActionResult Foo(Bar quux)
{
return new ResponseMessageResult(new BazHttpResponseMessage());
}
which should allow your current code to work as-is.
ASP.NET MVC had Methods RouteExistingFiles and IgnoreRoute on RoutesCollection:
routes.RouteExistingFiles = true;
routes.IgnoreRoute("{*relpath}", new { relpath = #"(.*)?\.(css|js|htm|html)" });
ASP.NET Core does not have these methods anymore. How can I let static files serve before dynamic content?
I have a problem serializing pcl class object because the class objects property is cannot be evaluated. The structure of my solution is having three projects -
Xamarin.Android, reference Services, and Dto
PCL (for Services), reference Dto (target frameworks: .Net Framework 4.5, ASP.Net Core 1.0, Windows 8, Windows Phone 8.1, Xamarin.Android, Xamarin.iOS, Xamarin.iOS(Classic)
PCL (for Dto)) (target frameworks: .Net Framework 4.5, ASP.Net Core 1.0, Windows 8, Windows Phone 8.1, Xamarin.Android, Xamarin.iOS, Xamarin.iOS(Classic)
I have one method in my service class like -
public async Task<HttpResponseMessage> SignIn(string username, string password)
{
var user = new Dto.UserLogin(username, password);
var serialize = Newtonsoft.Json.JsonConvert.SerializeObject(user);
var content = new StringContent(serialize);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = null;
using (var client = GetClient("{urlhere}", username, "POST"))
{
response = await client.PostAsync("api/{methodname}", content);
}
return response;
}
The code above does not throw error and can instantiate the "user" variable. However the problem was that when the serialization line happens, it serialize nothing. It seems like the "user" object is cannot access or show the two properties "Email" and "Password". But I can access them in debug using "user.Email". I've attached a screenshot of it.
Email and Password properties are public.
Thanks,
Marvin
The comment from #Jack helps me to figure out the culprit. In Xamarin.Android property settings->Android options->linker, currently it is set to "SDK and User assemblies". I changed it to "SDK Assemblies Only" and this solved the problem.
I created a simple WebAPI service in .NET4 and Visual Studio 2010.
I need to consume that service in a Windows CE / CF 3.5 app
I do have HttpWebRequest available to me, but am not sure if this is the way to go, or I should use RestSharp. Does anybody have insight/experience that would help me decide? I prefer not using 3rd party code when possible to avoid it, but am willing to do so if there is a clear advantage over the "raw" offerings.
Does anyone have, or know of, examples for accessing WebApi services using HttpWebRequest OR RestSharp from CF 3.5?
I have this code (adapted from from http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api) for sample WebAPI methods:
public class VendorItemsController : ApiController
{
VendorItem[] vendorItems = new VendorItem[]
{
new VendorItem { VendorId = "1", VendorItemId = "Tomato Soup", ItemId = "Groceries", PackSize = 1 },
new VendorItem { VendorId = "2", VendorItemId = "V8", ItemId = "Groceries", PackSize = 6 },
new VendorItem { VendorId = "3", VendorItemId = "Garlic", ItemId = "Groceries", PackSize = 1 },
};
public IEnumerable<VendorItem> GetAllProducts()
{
return vendorItems;
}
public VendorItem GetProductById(string id)
{
var vendorItem = vendorItems.FirstOrDefault((p) => p.VendorId == id);
if (vendorItem == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return vendorItem;
}
}
...but don't know how to consume this using, if possible, HttpWebRequest.
Note: HttpClient is not available to me (HttpWebRequest is, though).
UPDATE
I start the VS2010 app that has the WebAPI method; but when I run the VS2008 Windows CE / Compact Framekwork 3.5 app with this code:
Uri _baseAddress = new Uri("http://localhost:48614/");
string localFile = "fetchedVendorItems.txt";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(_baseAddress + "api/vendoritems/");
req.Method = "GET";
HttpWebResponse resp = (HttpWebResponse) req.GetResponse();
// Retrieve response stream and wrap in StreamReader
Stream respStream = resp.GetResponseStream();
StreamReader rdr = new StreamReader(respStream);
// Create the local file
StreamWriter wrtr = new StreamWriter(localFile);
// loop through response stream reading each line and writing to the local file
string inLine = rdr.ReadLine();
while (inLine != null)
{
wrtr.WriteLine(inLine);
inLine = rdr.ReadLine();
}
rdr.Close();
wrtr.Close();
(which I adapted from here: http://msdn.microsoft.com/en-us/library/aa446517.aspx)
...I get, "Unable to connect to the remote server"
UPDATE 2
This does work directly in the browser on the dev machine:
http://localhost:48614/api/redemptions/
It returns these values from a Controller:
readonly Redemption[] redemptions =
{
new Redemption { RedemptionId = "1", RedemptionName = "Old", RedemptionItemId = "ABC", RedemptionAmount = 0.25M, RedemptionDept = "2.0", RedemptionSubDept = "42" },
new Redemption { RedemptionId = "2", RedemptionName = "Damaged", RedemptionItemId = "BCD", RedemptionAmount = 5.00M, RedemptionDept = "42.0", RedemptionSubDept = "76" },
new Redemption { RedemptionId = "3", RedemptionName = "Rebate", RedemptionItemId = "DEF", RedemptionAmount = 42.75M, RedemptionDept = "76.0", RedemptionSubDept = "112" }
};
...like so:
<ArrayOfRedemption xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/HHSServerWebAPI.Models">
<Redemption>
<RedemptionAmount>0.25</RedemptionAmount>
<RedemptionDept>2.0</RedemptionDept>
<RedemptionId>1</RedemptionId>
<RedemptionItemId>ABC</RedemptionItemId>
<RedemptionName>Old</RedemptionName>
<RedemptionSubDept>42</RedemptionSubDept>
</Redemption>
<Redemption>
<RedemptionAmount>5.00</RedemptionAmount>
<RedemptionDept>42.0</RedemptionDept>
<RedemptionId>2</RedemptionId>
<RedemptionItemId>BCD</RedemptionItemId>
<RedemptionName>Damaged</RedemptionName>
<RedemptionSubDept>76</RedemptionSubDept>
</Redemption>
<Redemption>
<RedemptionAmount>42.75</RedemptionAmount>
<RedemptionDept>76.0</RedemptionDept>
<RedemptionId>3</RedemptionId>
<RedemptionItemId>DEF</RedemptionItemId>
<RedemptionName>Rebate</RedemptionName>
<RedemptionSubDept>112</RedemptionSubDept>
</Redemption>
</ArrayOfRedemption>
...even when the VS2008 project is not running - is that because this data was cached (the first time I entered:
http://localhost:48614/api/redemptions/
...in the browser, the Web API app was running)?
I get that the emulator won't recognize "localhost" as the desktop instance, considering itself someone/somewhere else. So how can I test this on an emulator? What IP address can I use?
Avoiding 3rd party code out of hand is just plain silly. Why reinvent the wheel? If you are a company who's IP is making REST calls, then sure, roll it, but I suspect your core business offering is in solving some other problem. I mean why use the CF itself, and not C? Why use C and not assembly? Why use a third-party processor and not design your own?
All that aside, RestSharp comes with source and it's free, so there's little risk in using it. There are some things I like about it - primarily that most of the grunt work for REST calls done. I'm a big fan of not reinventing things. It has some quirks that I've "fixed" locally (I'm meaning to do a pull request, just haven't found the time yet) but they were minor and not what I'd consider to be "typical" cases.
As for calling Web APIs with RestSharp, there's a pretty thorough coverage over in this article.