Bound function call returns InvalidOperationException - c#

I'm following this OData V4 tutorial and now have a problem with the bound function MostExpensive.
This function is bound to the Productscollection and is registered in WebApiConfig.Register() like suggested in the tutorial:
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "ProductService";
builder.EntityType<Product>().Collection.Function("MostExpensive").Returns<decimal>();
There is only described a rudimentary client for this service in part 2 of this tutorial. So I want to extend it so that I also can call the functions described in the later parts of the tutorial.
I have created the client using OData Client Code Generator as suggested in the tutorial. I then add some products and suppliers and then want to get the most expensive product:
static void Main(string[] args)
{
const string serviceUri = "http://localhost:52542";
Container container = new Container(new Uri(serviceUri));
AddProducts(container, GenerateSomeProducts());
AddSuppliers(container, GenerateSomeSuppliers());
Console.WriteLine("Most expensive product is: {0}", container.Products.MostExpensive().GetValue());
...
}
When calling GetValue() I am getting an InvalidOperationException stating that http://localhost:52542/$metadata refers to a Edm.Decimal type but a Collection(Edm-Decimal) type is expected.
When calling http://localhost:52542/Products/ProductService.MostExpensive() directly in the browser I'm getting
{
"#odata.context":"http://localhost:52542/$metadata#Edm.Decimal","value":40000.95
}
Which seems to be correct.
Do I do anything wrong? I have no idea how to fix this. So any suggestions about that?

I guess you are using T4 2.2.0, right?
There is a bug in T4 2.2.0 which causes this issue. You can use the content in following link to replace your ttinclude file and regenerate your proxy to work around the issue.
https://raw.githubusercontent.com/LaylaLiu/odata.net/T4TempFix/src/CodeGen/ODataT4CodeGenerator.ttinclude

Related

Inject AddSqlServer with another service

Is it possible to resolve an instance of ISettingsService from the ConfigureServices method in Startup(.cs) - webapplication?
I've implemented a SettingsService which is able to retrieve the database connectionstring from an external source (secure credentials store). Within the ConfigureServices I need an instance of the ISettingsService in order to get the connectionstring and pass it to the services.AddSqlServer<MyDbContext>(connectionstring) method.
While creating the instance (using var provider = services.BuildServiceProvider(); var settings = provider.GetService<ISettingsProvider>();) Visual Studio displays the next error:
Another developer posted a similar question on StackOverflow and the answer provides a solution in case of AddSingleton/ AddTransient. What is the correct way to apply it on the AddSqlServer call? Or could you provide another solution to avoid the warning/ error message?
The Intellisense comment for .AddSqlServer actually says to use .AddDbContext if you need more control, and that's certainly the correct option.
If you refer to the source code here, you can see that all .AddSqlServer is actually doing is calling .AddDbContext and configuring the options accordingly. We can therefore write our own solution like this:
services.AddDbContext<DbContext>((serviceProvider, options) => {
var settings = serviceProvider.GetService<ISettingsProvider>();
// I don't know what methods your ISettingsProvider makes available
// so adjust accordingly
string connectionString = settings.GetSetting("connectionString");
options.UseSqlServer(connectionString);
});
Of course you can make other changes to the options here, and .UseSqlServer can also take a Action<SqlServerDbContextOptionsBuilder> (options.UseSqlServer(connectionString, opts => opts.EnableRetryOnFailure()), etc.) to further configure it.

.NET: Retrieving Data From parse database

I have installed the Parse reference into my MVC Application by downloading it through Package Manager. The reference that has been added is Parse 1.5.5.
ParseClient.Initialize("app_key", ".net_key");
var test = new ParseObject("test");
test["username"] = "test";
test["password"] = "test";
test.SaveAsync();
ParseQuery<ParseObject> query = ParseObject.GetQuery("test");
ParseObject test1 = query.GetAsync("mVzhilmRJw");
The issue here is that GetAsync method returns ParseQuery type as opposed to ParseObject Type as mentioned in the documentation. Further, the metadata shows that the method GetAsync is not of Async type, which I presumably feel is the root cause.
The following is the error that I'm getting when I try to execute the LINQ version of the above method:
var query1 = ParseObject.GetQuery("test")
.WhereEqualTo("objectId", "W70H7Ad8rv");
IEnumerable<ParseObject> results =
(IEnumerable<Parse.ParseObject>)query1.FindAsync();
Error:
Unable to cast object of type 'System.Threading.Tasks.UnwrapPromise1[System.Collections.Generic.IEnumerable1[Parse.ParseObject]]' to type 'System.Collections.Generic.IEnumerable1[Parse.ParseObject]'.
I'm trying out Parse as the backend for the first time and not sure if I have included the appropriate references. Further I'm using .NET 4.5 framework, Visual Studio 2012 on a Windows 7 OS. Does this have anything to do with the issue I am facing.
Any help is highly appreciated.
TLDR: How do we retrieve data from Parse in a .NET Web application using .NET 4.5 framework, VS 2012 and what are the references corresponding to Parse that have to be added.
The solution for this issue turned out to be pretty straight forward. It is required that we know what async is all about. This can be found here.
It is important that an async method is called within an Async method only. The sample of code can be as seen below
public async void GetData()
{
ParseClient.Initialize("app_key", ".net_key");
var query1 = ParseObject.GetQuery("test").WhereEqualTo("objectId", "xxxxxxxx");
var result = await query1.FindAsync();
}
If you want to know how not to block on call to an async method, you can refer here.

How to use Delta<T> from Microsoft ASP.NET Web API OData with Code First\JsonMediaTypeFormatter

What is the issue?
I am trying to enable patching in my ASP.net web api app. I'm using code first entity framework.
I have the following method header which I can set a breakpoint in and it will hit:
[AcceptVerbs("PATCH")]
public async Task<HttpResponseMessage> Patch(long appId, long id, Delta<SimpleFormGroup> formGroup)
However when I call formGroup.Patch(entity), no changes are made to my entity. If I put the following into the immediate window:
formGroup.GetChangedPropertyNames()
Then this collection is empty, which seems wrong.
What have I tried?
I have been referring to the following examples
http://techbrij.com/http-patch-request-asp-net-webapi
http://www.strathweb.com/2013/01/easy-asp-net-web-api-resource-updates-with-delta/
It seems to be a problem with the Json MediaType Formatter not knowing how to build the Delta object correctly, however in the 2nd link filip does seem to suggest that it should work without the oDataMediaTypeFormatter.
I have started down the line of trying to serialise my model to EDMX representation, then from there extract the CSDL so I can create an oDataMediaTypeFormatter, but I have hit a snag there too, plus it seems a bit overkill.
If anyone could shed any light on this it'd be much appreciated. Let me know if any more information is needed.
EDIT:
Here is the class definition for SimpleFormGroup:
public class SimpleFormGroup
{
public int LastUpdate;
public string Identifier;
public string Title;
public int DisplayOrder;
}
And here is the data that I am sending:
Content-Type: 'application/json'
{ "DisplayOrder" : "20 }
Interesting, it looks like Delta<T> with int members doesn't work in JSON.
Unfortunately, Delta<T> was created specifically for OData. If Delta<T> appears to be working with any formatter other than OData, it's a coincidence rather than being intentional.
The good news though is that there's nothing stopping you from defining your own PATCH format for JSON, and I'd be surprised if no one has already written one that works better with Json.NET. It's possible that we'll revisit patching in a future release of Web API and try to come up with a consistent story that works across formatters.
Thanks to Youssef for investigating and discovering why things weren't working. Hopefully that can get solved down the line.
I managed to crack this myself in the end after poring over the oData package source. I chose to implement another MediaTypeFormatter that wraps up the logic as it provides easy access tio HttpContent, but there are other ways to achieve this.
The key part was figuring out how to interpret the code first model, see the commented line below:
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var builder = new ODataConventionModelBuilder();
// This line will allow you to interpret all the metadata from your code first model
builder.EntitySet<EfContext>("EfContext");
var model = builder.GetEdmModel();
var odataFormatters = ODataMediaTypeFormatters.Create(model);
var delta = content.ReadAsAsync(type, odataFormatters).Result;
var tcs = new TaskCompletionSource<object>();
tcs.SetResult(delta);
return tcs.Task;
}
Hope this saves someone some trouble!

a proxy type with the name account has been defined by another assembly

We have 2 orgs running in our on-premise crm 2011 system.
We have generated early bound classes for both orgs.
One of our plugins is throwing the "a proxy type with the name account has been defined by another assembly" error when deactivating an account.
That plugin only references one of the early bound dll's.
How do I get the CRM system to respect the namespace of these references.
I've tried the few items that show up from Google and none are working.
Since you can reproduce this with 2 vanilla orgs I would imaging there is something OUTSIDE the code layer we can do without having to go back and refactor a bunch of code for the 2 orgs.
Thanks,
Jon
The problem is actually with WCF attempting to deserialize the server response and not being able to identify the correct type. The best method to sort this issue is to pass in the current assembly using Assembly.GetExecutingAssembly() to the ProxyTypesBehavior() while creating the proxy like so.
using (serviceProxy = new OrganizationServiceProxy(config.OrganizationUri,
config.HomeRealmUri,
config.Credentials,
config.DeviceCredentials))
{
// This statement is required to enable early-bound type support.
serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior(Assembly.GetExecutingAssembly()));
}
You may run into this issue when referencing different assemblies containing proxy-classes, i.e. one assembly wrapping the server SDK (Microsoft.Xrm.Sdk) and another assembly wrapping the client SDK (Microsoft.Xrm.Sdk.Client).
In such a scenario it seems to be required to tell the OrganizationServiceProxy which assembly should be used to resolve the proxy classes.
This should help:
var credentials = new ClientCredentials();
credentials.Windows.ClientCredential = new System.Net.NetworkCredential(userName, password, domain);
var proxy = new OrganizationServiceProxy(new Uri(discoveryUrl), null, credentials, null);
proxy.EnableProxyTypes(typeof(CrmServiceContext).Assembly);
var context = CrmServiceContext(proxy);
The important thing is to call EnableProxyTypes by passing the correct assembly. I saw another solution using CrmConnection but CrmConnection is only available in the client SDK, which means that you can't instantiate a "server-OrganizationServiceProxy" this way. EnableProxyTypes(Assembly assembly) works for both sides.
Hope this helps.
Regards,
MH
It maybe years since this question has been raised. However, I faced this problem recently and have been extremely worried about thousands of lines of code to be changed. However, I was lucky to find the following simple change to get myself out of hell:
Suppose there are two context objects you deal with:
an OrganizationServiceContext object: context1
a CrmSvcUtil Context object: context2
and a single OrganizationServiceProxy object: service
if in a single method, you make multiple CRUD operations using the same service object but with either of context objects as exemplified above, it is highly probable that this error be raised. However, by doing the following, you can prevent it to happen.
Every time you want to work with context1, you precede the context object with the service object as following:
service.EnableProxyTypes(typeof(OrganizationServiceContext).Assembly);
using (var context1 = new OrganizationServiceContext(_service)){
// your classic code here
}
Also, every time you want to work with context2, you follow the same structure:
service.EnableProxyTypes(typeof(HiwebContext).Assembly);
using (var context = new XYZContext(this._service)){
// your CrmSvcUtil none-classic code here
}
this normally means that there is one or more assemblies with the same method name or property to fix this use the fully qualified name of the assembly.. for example in the using System.IO for example if you had a method named the same way in your Class code that conflicts with System.IO.... you would write your fix like
thisObject.System.IO.Path( ---- ) = somthing for example.. does this make sense..?
I found that adding the Assembly.GetExecutingAssembly() solved the problem.
adding the Assembly.GetExecutingAssembly() solve my problem, you also need to add using System.Reflection;
thanks

OAuth in C# as a client

I've been given 6 bits of information to access some data from a website:
Website Json Url (eg: http://somesite.com/items/list.json)
OAuth Authorization Url (eg: http://somesite.com/oauth/authorization)
OAuth Request Url (eg: http://somesite.com/oauth/request)
OAuth Access Url (eg: http://somesite.com/oauth/access)
Client Key (eg: 12345678)
Client Secret (eg: abcdefghijklmnop)
Now, I've looked at DotNetOpenAuth and OAuth.NET libraries, and while I'm sure they are very capable of doing what I need, I just can't figure out how to use either in this way.
Could someone post some sample code of how to consume the Url (Point 1.) in either library (or any other way that may work just as well)?
Thanks!
I also just started working with OAuth a month ago and was also confused by all these libraries. One thing I realized about these libraries is that they're quite complicated (as you have found out). Another thing that makes it hard is that there wasn't a lot of example (it was worse in my case because I was trying to implement a Provider and not a Client).
Originally, I wanted to use the latest OAuth 2.0 but the only .NET library out there that implements it is DotNetOpenAuth. It's probably one of the most complete .NET OAuth library out there but it'll take too long for me to understand (due to not knowing WCF, MVC, etc). I have since downgraded to OAuth 1.0a because I found these examples for DevDefined OAuth. I don't know about you but I found it easier to learn from examples.
It looks like you only want to implement a Client so make sure to look at the Consumer examples. Try to compile the examples and ignore the Provider examples because you don't need them and it'll make you more confused. Be patient. If you're still confused, it might be a good idea to look at some of the libraries made for other languages as they might have easier to understand documentations.
OK, I know your last post was months ago, but in case you were still working on this (or for people like me who would have loved to see an answer to this question), here's some information regarding the NullReferenceException you encountered creating the OAuth request:
The null reference comes from the IServiceLocator that is used to resolve dependencies. If you don't explicitly pass one into the constructor, it uses the static property ServiceLocator.Current in the Microsoft.Practices.ServiceLocation namespace.
This is one of the many pitfalls of using static methods and global state, is you hide issues like this from the consumer of your API. So if you haven't specified a default service locator, then null is returned, resulting in the NullReferenceException.
So to fix this issue, I wired up an implementation of IServiceLocator that uses StructureMap (one of the many IoC containers available) as the container. Lastly, you will need to register instances for two interfaces: ISigningProvider and INonceProvider. Luckily, several standard implementations exist in the OAuth.Net.Components assembly, such as GuidNonceProvider and HmacSha1SigningProvider.
The resulting code looks like something like this:
var container = new Container();
container.Configure(a => a.For<INonceProvider>().Use<GuidNonceProvider>());
container.Configure(a => a.For<ISigningProvider>()
.Use<HmacSha1SigningProvider>()
.Named("signing.provider:HMAC-SHA1"));
var locator = new StructureMapAdapter(container);
ServiceLocator.SetLocatorProvider(delegate { return locator; });
I realize this isn't the final solution to your original question (I'm still working on getting it working myself), but I hope it gets you a few steps further. And if you've long abandoned this implementation altogether... well, happy coding anyway!
For OAuth 2.0:
I learned that it's easiest to just put up the authentication page in an HTML window then trap the returned access_token. You can then do that using in client-side web browser.
For example, in MonoTouch it would be:
//
// Present the authentication page to the user
//
var authUrl = "http://www.example.com/authenticate";
_borwser.LoadRequest (new NSUrlRequest (new NSUrl (authUrl)));
//
// The user logged in an we have gotten an access_token
//
void Success(string access_token) {
_web.RemoveFromSuperview();
var url = "http://www.example.com/data?access_token=" + access_token;
// FETCH the URL as needed
}
//
// Watch for the login
//
class Del : UIWebViewDelegate
{
public override void LoadingFinished (UIWebView webView)
{
try {
var url = webView.Request.Url.AbsoluteString;
var ci = url.LastIndexOf ("access_token=");
if (ci > 0) {
var code = url.Substring (ci + "access_token=".Length);
_ui.Success (code);
}
} catch (Exception error) {
Log.Error (error);
}
}
}

Categories