I am trying to create an instance of ODataQueryContext which requires an EdmModel reference. I am attempting to get the Model from ODataProperties() which is a method call off of the HttpRequestMessage object.
var orderBy = new OrderByQueryOption("ColumnName desc", new ODataQueryContext(Request.ODataProperties().Model, typeof(MyType)));
It seems that if I use the namespace using System.Web.Http.OData.Extensions; as opposed to using System.Web.OData.Extensions; the Model property is available from ODataProperties(). However, I am using the newer version (OData v4) namespaces, for other references in my program.
After doing some research I determined that with OData v4, they moved everything from Web.Http.OData.* namespaces, to Web.OData.* namespaces. I am assuming that I need to be consistent in using either the new or old namespaces, and I was not successful attempting to mix them.
Does anyone know how to get the Model property from ODataProperties() without using the older Web.Http.OData namespaces?
To anyone still having trouble with this (I ended-up here from a MS OData tutorial) request.ODataProperties().Model has changed to request.GetModel() ( HttpRequestMessageExtensions in namespace Microsoft.AspNet.OData.Extensions in assembly Microsoft.AspNet.OData). Also request.ODataProperties().PathHandler has changed to request.GetPathHandler().
In ASP.NET Core 3.1, package Microsoft.AspNetCore.OData, most values under Request.ODataProperties() are now under Request.ODataFeature().
ODataProperties().Model from OData on github
Related
We have ASP.NET MVC 5 project, that we have plans to migrate to ASP.NET Core 3. Currently I gather dependency list and their equivalent replacements on the new new platform.
We are using MvcCodeRouting package to separate different workflows between different C# namespaces as was described in https://maxtoroq.github.io/2013/02/aspnet-mvc-workflow-per-controller.html.
Now with new platform in place, we need something similar. As last resort we could just specify all our namespaces in routing table, but I'd rather not to do so.
Any suggestions on how accomplish similar behavior?
EDIT:
I think with example it would be more understandable what I'm trying to accomplish.
We have following structure of controllers:
- Namespace1
-- Workflow1Controller.Index/Edit/Action
-- Workflow2Controller.Index/Edit/Action
-- Workflow3Controller.Index/Edit/Action
- Namespace2
-- Workflow4Controller.Index/Edit/Action
Workflow1Controller code:
namespace RootProjectNamespace.Controllers.Namespace1
{
class Workflow1Controller : Controller
{
public ActionResult Index() {}
// and so on
}
}
Appropriate Views are placed in similar manner.
And using MvcCodeRouting we able to create Action urls by following:
Url.Action("Namespace1.Workflow1Controller", "Index") // Creates -> ~/Namespace1/Workflow1Controller/Index
Url.Action("Namespace2.Workflow4Controller", "Action") // Creates -> ~/Namespace2/Workflow4Controller/Index
Is there possibility to achieve similar in .net core without explicit hardcoding routes in route table?
As an start point for your solution, you can create a custom IApplicationModelConvention and change the routing to use namespace in the routing.
There's an example in docs showing how you can do this. To learn more you can take a look at this great docs article: Work with the application model in ASP.NET Core.
To do so, first create the following NamespaceRoutingConvention class:
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using System.Linq;
public class NamespaceRoutingConvention : IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
foreach (var controller in application.Controllers)
{
var hasAttributeRouteModels = controller.Selectors
.Any(selector => selector.AttributeRouteModel != null);
if (!hasAttributeRouteModels)
{
controller.Selectors[0].AttributeRouteModel = new AttributeRouteModel()
{
Template = controller.ControllerType.Namespace.Replace('.', '/')
+ "/[controller]/[action]/{id?}"
};
}
}
}
}
Then in startup, register the convention like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options => {
options.Conventions.Add(new NamespaceRoutingConvention());
});
}
Then you can browse:
http://localhost:xxxxx/SampleProject/Controllers/Home/Index
I have recently come across this issue.
An MVC .NET Framework project I had been working on needed migrating to .NET Core, however it was made up from lots of smaller assemblies (DLLs), each containing different parts of the overall codebase.
MvcCodeRouting was used to implement this, and provided a way for the assemblies to be utilised, routed, and also provided the ability for the central (core) project to utilise the relevant views, stored within the assemblies.
I have found that the .NET Core "Application Parts" feature seems to fulfill most of these points, with it having the ability for projects to be seperated between different assemblies, imported into a main project, and utilised.
The only real functional difference in using this method is that each "Application Part" generates two assemblies instead of one, with one containing the controllers and module logic, whilst the other contains the (Razor) views (if the specific module has any).
I'm still experimenting with this, however I thought I'd add this here for the sake of completeness.
Below are some useful links to documentation regarding this feature:
https://learn.microsoft.com/en-us/aspnet/core/mvc/advanced/app-parts?view=aspnetcore-1.0#sample-generic-controller-feature
This is the main documentation for the feature within the ASP.NET Core documentation.
https://learn.microsoft.com/en-us/aspnet/core/razor-pages/ui-class?view=aspnetcore-1.0&tabs=visual-studio
This tutorial demonstrated creating an assembly containing only Razor Views, if some of the modules require no logic.
Other than changing startup.cs whenever a new version is built,
services.AddApiVersioning(config =>
{
config.DefaultApiVersion = new ApiVersion(1, 0);
});
is there a way of specifying that the "default version" is the latest version, without specifying what that version is? e.g. some way of saying
config.DefaultApiVersion = new ApiVersionLatest();
. . . or does this fly in the face of all that is considered holy by the RESTApi gods?
Thanks
The correct answer depends a little bit about what you expect to achieve. The DefaultApiVersion only comes into play when no other API version is available. API versioning does not have a concept of "no API version". API version-neutral means that an API accepts any and all API versions, including none at all. The default API version can also be thought of as the initial API version.
Here's a few scenarios where the DefaultAPiVersion comes into play:
A controller has no attribution or conventions applied
Selection of possible API versions yields no results
It sounds like you are interested in configuring the most current API version in a single place. You can use the DefaultApiVersion to do this, but only if the controller has no other attribution or conventions. If an API doesn't carry forward, you will have to explicitly decorate the controller with an attribute or convention that indicates the legacy API version to exclude it from the latest version. While this is possible, it's hard to follow IMO.
A better approach would probably to use an extension that that describes the behavior you want. For example:
[AttributeUsage( AttributeTargets.Class, AllowMultiple = false )]
public sealed class LatestApiVersionAttribute : ApiVersionAttribute, IApiVersionProvider
{
public LatestApiVersionAttribute() : base( new ApiVersion( 2, 0 ) ) { }
}
Now you can apply this to all your controllers a la:
[LatestApiVersion]
public class MyController : ControllerBase
{
// ommitted
}
This gives you the chance to manage the latest API version is single place. You might also consider using conventions so you don't even need the custom attribute. Attributes and conventions can be combined.
#spender does mention using a custom IApiVersionSelector; however, selection currently only comes into play when no API version has been specified. To enable this type of configuration, set things up as:
services.AddApiVersioning( options =>
{
options.ApiVersionSelector = new CurrentImplementationApiVersionSelector( options );
options.AssumeDefaultVersionWhenUnspecified = true;
}
This will enable clients that do not specify an API version to always forward to the most recent version of the requested API. A client can still explicitly ask for a specific version, including the latest.
I hope that helps.
We have a WEB API project that recently was moved to a new server. I'm running my project after making some additions to its' payload, but it suddenly throws the following error:
Unable to cast object of type
'System.Net.Http.Formatting.JsonContractResolver' to type
'Newtonsoft.Json.Serialization.DefaultContractResolver'.
The offending line of code is in global.asax:
protected void Application_Start() {
GlobalConfiguration.Configure(WebApiConfig.Register);
var serializerSettings =
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
var contractResolver =
(DefaultContractResolver)serializerSettings.ContractResolver;
contractResolver.IgnoreSerializableAttribute = true;
}
I believe this code was added because the default output of the API was XML, and we need it to be JSON instead.
Highlighting (DefaultContractResolver) brings up a tooltip indicating it references NewtonSoft.JSon.Serialization.DefaultContractResolver. Highlighting serializersettings.ContractResolver references IContractResolver JSonSerializerSettings.ContractResolver.
The code has been on this machine for some time, and the only thing I can think I changed was installing a newer version of .NET.
What could cause this line of code to suddenly throw an error? And how can I resolve it?
Thanks!
Edit: As per request in the comments, my serialization code consists of something like the following:
json += "{\"employeename\": \"" + Convert.ToString(reader["Employee"])
+ "\"},";
return JsonConvert.DeserializeObject<OrgChartModel>(json);
Edit2: We're now running .NET 4.5. To the best of my knowledge, we ran 4.2 prior, but seeing it's been a few months, I cannot be sure.
As per comment by Dominick, I tried changing the cast to DefaultContractResolver to the following:
var contractResolver =
(IContractResolver)serializerSettings.ContractResolver;
This, however, then ends up in the API returning the following error:
{"Message":"The requested resource does not support http method 'GET'."}
What I understand from this code is that you just try to set the IgnoreSerializableAttribute of your resolver to true.
1> Do you know why it has to be done? What are the effect if your remove it?
I can see from the Newton Doc that setting IgnoreSerializableAttribute to true will stop Newtonsoft.Json from behaving like Microsoft's serialisers and instead just serialise the public properties.
Do you still need that?
2> What is the type of your current SerializerSettings (we only know it's not the default one, so you probably change it somewhere?) Are you sure it still has IgnoreSerializableAttribute to false by default? If so you probably has a way to reach this attribute using the actual type?
Hope it helps
I managed to solve the issue by using a newer version of JSON.NET (8, where before we were using version 6). This resolved the error.
I have created a solution using the empty asp.net template.
I have addred Ormlite and MySql Servicestatck libraries and configured them in the Apphost.cs
ConnectionStringSettings connstring = ConfigUtils.GetConnectionStringSetting("Nice2NoConnection");
container.Register<IDbConnectionFactory>(new OrmLiteConnectionFactory(connstring.ToString(), MySqlDialectProvider.Instance));
// Below we refer to the connection factory that we just registered
// with the container and use it to create our table(s).
using (var db = container.Resolve<IDbConnectionFactory>().Open())
{
// We’re just creating a single table, but you could add
// as many as you need. Also note the “overwrite: false” parameter,
// this will only create the table if it doesn’t already exist.
db.CreateTable<Channel>(overwrite: false);
What I am having trouble figuring out is how to access the OrmliteWriteExtensions which include Save() in the ServiceInterface project. I tried adding Ormlite and MySql there but don't know how to access the reference of the connectionfactory in this project.
I think my issue relates to a lack of deeper understanding of IoC
I am probably over complicating something here.
Suggestions?
TIA
Thank you for the feedback. I wish to thank you for such a fantastic library. My issues turns out was my lack of understanding of IoC and I had to do code like: var conn = HostContext.Container.Resolve<IDbConnection>();
conn.Open();
conn.Save<Channel>(channel);
The OrmLite extension methods are under the ServiceStack.OrmLite namespace so to access them you just need to import:
using ServiceStack.OrmLite;
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