I am getting this error randomly at the production server here is the stack trace of the error. I am using linq to sql and .net 4.0
System.ArgumentException: An item with the same key has already been added.
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Data.Linq.DataContext.GetTable(MetaTable metaTable)
at System.Data.Linq.DataContext.GetTable[TEntity]()
at UserManagement.Models.EvoletDataContext.get_sysModules() in D:\MyProj\Models\datamdl.designer.cs:line 1294
at UserManagement.Models.FilterRepository.GetModuleHead(String actionName) in D:\MyProj\Models\FilterRepository.cs:line 14
at UserManagement.Models.DummyAttrib.OnAuthorization(AuthorizationContext filterContext) in D:\MyProj\Models\Filters.cs:line 44
at Glimpse.Net.Plumbing.GlimpseAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext)
at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.Controller.ExecuteCore()
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
at System.Web.Mvc.MvcHandler.<>c__DisplayClasse.<EndProcessRequest>b__d()
at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Code at line 14 is below. I have also included the datacontext
private EvoletDataContext db = new EvoletDataContext();
public sysModule GetModuleHead(string actionName)
{
var val = (from mod in db.sysModules
where
mod.ModuleActionResult.ToLower().Equals(actionName.ToLowerInvariant())
select mod).SingleOrDefault();
return val;
}
Code at line 44 is
public class DummyAttrib:FilterAttribute,IAuthorizationFilter
{
private readonly FilterRepository _filterRepository = new FilterRepository();
public void OnAuthorization(AuthorizationContext filterContext)
{
if (!filterContext.Controller.ControllerContext.IsChildAction && !filterContext.HttpContext.Request.IsAjaxRequest())
{
var cont = (ApplicationController)filterContext.Controller;
var modhead = _filterRepository.GetModuleHead(filterContext.RouteData.Values["action"].ToString());
if (cont.DocumentID != 0 && modhead !=null)
{
if (_filterRepository.hasRightonModuleChildren(modhead.ModuleID, cont.RoleID))
return;
}
if (cont.DocumentID == 0 && !filterContext.RouteData.Values["action"].ToString().ToLowerInvariant().Equals("index"))
{
filterContext.Result = new RedirectResult("/account.mvc/AccessDenied");
return;
}
if (!_filterRepository.hasRighton(cont.DocumentID, cont.RoleID))
{
filterContext.Result = new RedirectResult("/account.mvc/AccessDenied");
return;
}
}
}
}
LINQ maintains a 'cache' of sorts of tables you have already used, to prevent having to look them up multiple times.
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Data.Linq.DataContext.GetTable(MetaTable metaTable)
at System.Data.Linq.DataContext.GetTable[TEntity]()
The table you're trying to use hasn't been used within the data context before, so it's being added to the 'cache'. One of the ways this could fail is if you're calling GetTable() from multiple threads simultaneously, which suggests you're using a single data context for the entire application, which is not a good idea. Also, don't use the same data context if you're executing tasks in parallel.
I have a same problem. I've solved it.
Actually I have a duplicate property with the same name in my ViewModel.
One Property was in BaseViewModel and another is in derived Model.
For Example
public class BaseviewModel{
public int UserId { get; set; }
}
public class Model : BaseViewModel
{
public int UserId { get; set; }
}
I have changed them as
public class BaseviewModel{
public int UserId { get; set; }
}
public class Model : BaseViewModel
{
public int User_Id { get; set; }
}
Now it is working fine.
It looks like a bug - but MS have fixed it for .NET 4
http://connect.microsoft.com/VisualStudio/feedback/details/496178/linq-to-sql-projection-throws-argumentexception-an-item-with-the-same-key-has-already-been-added
Are you overriding any properties in your model classes?
Hope this helps,
Matt
I had the same error but the cause was one of my many-to-one relationships being defined with the wrong ends as the primary and secondary keys in the relationship.
Using the SQL Server Management Studio designer it was too easy to drag-drop from the child table to the parent table and miss the difference in the created relationship.
Check that all your relationships are correctly defined.
We have had similar problems after couple of months of deployment in production server. After doing some research I found out that sometimes there is a problem with LINQ closing connection automatically. Now we are specifically closing all the LINQ TO SQL connection via static extension method. Sample code:
public static void extClose(this System.Data.Linq.DataContext dataContext, bool submitChanges)
{
if (null != dataContext && System.Data.ConnectionState.Closed != dataContext.Connection.State)
{
if (true == submitChanges)
{
dataContext.SubmitChanges();
}
dataContext.Connection.Close();
}
}
I got the same issue in EF 4.1. with an existing application.
What happened? The EF 4.1 requires the .net framework 4.0. Windows update replaced the .net framework 4.0 with 4.5 and I got the same error you got.
The solution was to uninstall .net 4.5 and install .net 4.0.
On the production machine you should set the windows to skip the update to 4.5.
Related
I have created a Repository on top of Entity Framework Core, but have some issues with how it's done.
This is an example:
public class StockPricesRepository : IStockPricesRepository
{
StockPricesDbContext _stockPricesDbContext;
ILogger _logger;
public StockPricesRepository(StockPricesDbContext stockPricesDbContext, ILogger logger)
{
_stockPricesDbContext = stockPricesDbContext;
_logger = logger;
}
public void Add(StockPrice stockPrice)
{
_stockPricesDbContext.Add(stockPrice);
_stockPricesDbContext.SaveChanges();
}
public void AddOrUpdate(StockPrice stockPrice)
{
if (!Exists(stockPrice))
_stockPricesDbContext.Add(stockPrice);
else
_stockPricesDbContext.Update(stockPrice);
_stockPricesDbContext.SaveChanges();
}
private bool Exists(StockPrice stockPrice)
{
StockPrice existingStockPrice = Get(stockPrice.Ticker, stockPrice.Exchange, stockPrice.Date, stockPrice.DataProvider);
return (existingStockPrice != null);
}
public StockPrice Get(string ticker, string exchange, DateTime date, string providerName)
{
StockPrice stockPrice = null;
stockPrice =
(from sp in _stockPricesDbContext.StockPrices
where (
(sp.Ticker == ticker) &
(sp.Exchange == exchange) &
(sp.Date == date) &
(sp.DataProvider == providerName))
select sp).AsNoTracking().FirstOrDefault();
return stockPrice;
}
}
}
The StockPricesDbContext is injected into the constructur using dependency injection like this:
services.AddDbContext<StockPricesDbContext>(options => options.UseSqlServer(connectionString));
The problem with the current design is that I get some issues with multiple calls into the repository within the lifetime of the StockPricesDbContext object (even if I have AsNoTracking() on the Get method):
System.InvalidOperationException: 'The instance of entity type 'StockPrice' cannot be tracked because another instance with the same key value for {'Date', 'Ticker', 'Exchange', 'DataProvider'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.'
To avoid this problem I would maybe prefer to have each of the repository methods embedded in a using block like this:
using (var db = new StockPricesDbContext())
{
}
The problem with this approach is that I don't get the StockPricesDbContext from dependency injection and the connection string from AddDbContext is lost.
One workaround for that might be to get the connection string from the constructor of the repository like this:
private string _connectionString;
public StockPricesRepository(StockPricesDbContext stockPricesDbContext, ILogger logger)
{
_stockPricesDbContext = stockPricesDbContext;
_connectionString = stockPricesDbContext.Database.GetDbConnection().ConnectionString;
_logger = logger;
}
I would also need to add this constructor in StockPricesDbContext:
public StockPricesDbContext(string connectionString)
{
_connectionString = connectionString;
}
and this would be the OnConfiguring method:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
if (_connectionString != null)
optionsBuilder.UseSqlServer(_connectionString);
}
}
Then I could use it in the methods like this:
using (var db = new StockPricesDbContext(_connectionString))
{
}
It kind of works, but seems a bit "unclean".
Has anyone else come across a good pattern for repositories built on top of Entity Framework Core?
The common mistake that causes this error is having several async queries that have not been committed.
There is no problem saving multiple records in EF though.
There are multiple approaches to avoid your issue.
Using AddRange(),UpdateRange(),DeleteRange()
AddRange() can add list of objects to your db and you don't need to call .Add() more than once. Similarly you can update or delete a list of objects
EFCore.BulkExtensions
Bulk Extensions in EFCore
Both are extending DbContext with Bulk operations and have the same syntax call:
context.BulkInsert(stockPriceList);
context.BulkUpdate(stockPriceList);
context.BulkDelete(stockPriceList);
context.BulkInsertOrUpdate(stockPriceList);
We are trying to move to using an in-memory SQLite instance for our unit test automation, instead of SQL Server or SQL Express. We use Entity Framework Core.
I think I have everything configured correctly, but it's still failing, so I must be missing a step, but I'm not sure what it is.
In our test project's app.config, I've specified:
<connectionStrings>
<add name="BusinessDb" providerName="System.Data.SQLite.EF6" connectionString="data source=:memory:"/>
</connectionStrings>
Our production concrete class is a bit more complex (it has many more modelBuilder calls in the OnModelCreating() method and many more DbSet objects, but it is basically like this:
namespace Business.Base.Concrete
{
public class SqlBusinessDb
: DbContext
, IBusinessDb
{
public string ConnectionString { get; set; }
public SqlBusinessDb(string connectionString)
{
ConnectionString = connectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
if (ConnectionString.Contains("memory"))
{
optionsBuilder
.UseLazyLoadingProxies()
.UseSqlite(ConnectionString,
options =>
options.CommandTimeout(SqlSettings.s_CommandTimeoutInSec.CurrentValue)
.MigrationsHistoryTable("_BusinessDB_Migrations"))
.AddInterceptors(new Deals.Base.SQL.SqlPerfCounterInterceptor());
}
else
{
optionsBuilder
.UseLazyLoadingProxies()
.UseSqlServer(ConnectionString,
options =>
options.CommandTimeout(SqlSettings.s_CommandTimeoutInSec.CurrentValue)
.MigrationsHistoryTable("_BusinessDB_Migrations")
.EnableRetryOnFailure())
.AddInterceptors(new Deals.Base.SQL.SqlPerfCounterInterceptor());
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Has<BillingPlan>()
.HasManyToOne(p => p.Companies, a => a.BillingPlan, a => a.BillingPlan_Id)
}
public int ExecuteStoreCommand(string commandText, params object[] parameters)
{
return Database.ExecuteSqlRaw(commandText, parameters);
}
public DbSet<Features.FeatureOverride_Plan> FeaturesPlan { get; set; }
public DbSet<Business> Businesses { get; set; }
}
}
In our test project we call it like so:
public static TestBusinessDb GetInstance()
{
SqlBusinessDb realRepository = new SqlBusinessDb();
if (!_hasBeenMigrated)
{
_hasBeenMigrated = true;
DatabaseFacade dbf = realRepository.Database;
var issqlite = dbf.IsSqlite();
var tables = dbf.ExecuteSqlRaw("SELECT * FROM information_schema.tables;");
// for the Test Repository, we migrate once when we first try and connect.
realRepository.Database.Migrate();
}
}
This code fails on the "dbf.ExecuteSqlRaw()" line with:
Microsoft.Data.Sqlite.SqliteException : SQLite Error 1: 'no such table: information_schema.tables'.
If I remove that line, it fails on: realRepository.Database.Migrate(); with
Microsoft.Data.Sqlite.SqliteException : SQLite Error 1: 'no such table: _BusinessDB_Migrations'.
When debugging it successfully ran the OnConfiguring and OnModelCreating methods and I watched it execute a SQL command that created that table. dbf.ProviderName returns "Microsoft.EntityFrameworkCore.Sqlite". So, why aren't the tables being found? Is there something else that needs to be in place that I'm missing?
It turns out that SQLite is unable to handle migrations anyway, so it is not a viable option.
We're using ASP.NET WebAPI with Entity Framework (with lazy loading) and using Json.NET for serializing the data to JSON before returning the data to the client.
We are experiencing intermittent sudden spikes in memory usage which we suspect might originate with Json.NET not recognizing reference loops when serializing data (since Entity Framework might be doing some lazy loading voodoo with proxy classes which goes under the radar of Json.NET).
I thought I'd limit how deep Json.NET was allowed to go to serialize data (at least then we'd get a sensible exception when this happens so we could fix it in the data model), but I soon discovered that the MaxDepth property of JsonSerializerSettings only kicks in when DEserializing objects.
Is there any known way of imposing a limit on Json.NET when serializing?
I can't think of a way to do this out-of-the-box with Json.NET, since (as you correctly observe) MaxDepth is ignored when serializing. What you could do is to subclass JsonTextWriter and do the checks yourself:
public class MaxDepthJsonTextWriter : JsonTextWriter
{
public int? MaxDepth { get; set; }
public int MaxObservedDepth { get; private set; }
public MaxDepthJsonTextWriter(TextWriter writer, JsonSerializerSettings settings)
: base(writer)
{
this.MaxDepth = (settings == null ? null : settings.MaxDepth);
this.MaxObservedDepth = 0;
}
public MaxDepthJsonTextWriter(TextWriter writer, int? maxDepth)
: base(writer)
{
this.MaxDepth = maxDepth;
}
public override void WriteStartArray()
{
base.WriteStartArray();
CheckDepth();
}
public override void WriteStartConstructor(string name)
{
base.WriteStartConstructor(name);
CheckDepth();
}
public override void WriteStartObject()
{
base.WriteStartObject();
CheckDepth();
}
private void CheckDepth()
{
MaxObservedDepth = Math.Max(MaxObservedDepth, Top);
if (Top > MaxDepth)
throw new JsonSerializationException(string.Format("Depth {0} Exceeds MaxDepth {1} at path \"{2}\"", Top, MaxDepth, Path));
}
}
Then, to manually generate a JSON string, you would use it like this:
var settings = new JsonSerializerSettings { MaxDepth = 10 };
string json;
try
{
using (var writer = new StringWriter())
{
using (var jsonWriter = new MaxDepthJsonTextWriter(writer, settings))
{
JsonSerializer.Create(settings).Serialize(jsonWriter, myClass);
// Log the MaxObservedDepth here, if you want to.
}
json = writer.ToString();
}
Debug.WriteLine(json);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
throw;
}
Demo fiddle here.
Since your tags include web-api, if you want to do this check inside web API calls, you could follow Rick Strahl's instructions to create a custom MediaTypeFormatter for JSON: Using an alternate JSON Serializer in ASP.NET Web API; then use the code above in the OnWriteToStreamAsync method when generating the json string.
we use a StateServer for handling Session for the known benefits (web farm, IIS recycling).
However I am trying to figure out how to make this fault tolerant. Nothing we store in the Session is critical, it is just used for performance. So if the StateServer is not available we are happy to reload from disk.
However there appears to be no way of detecting if the StateServer is online or not, so the following code all runs fine even if the StateServer is down
try
{
//It is not NULL as it has been configured
if (HttpContext.Current.Session != null)
Session["Test"] = "value";
}
// No exception is thrown
catch (Exception)
{
throw new Exception();
}
Now it makes sense to me that no exception is thrown. The Session handling would not be very performant if it had to check the status on every write. So I am guessing what happens is that it writes all the Session vaiables when the Response is written.
There lies the problem, when it tries to write the Session it fails with a 500 error and I do not know anyway to intercept this error and handle it.
Unable to make the session state request to the session state server.
Please ensure that the ASP.NET State service is started and that the
client and server ports are the same.
What I would like to happen is that the write just fails silently (or logs an error) and clients are not impacted. As it is write now the entire site goes down due to this single point of failure.
Any ideas - am I missing something obvious?
well, it can be hard. Asp.net uses session tightly, so if session storage fails, it asp.net will also fails during initialization of session module. You can write own session state provider, that will wrap existing one, and in case of fail it will return empty session items, but it can be hard to use it, because session behavior can be unpredictable.
You can look into built in SQL session state provider, that has failover in case if your SQL server has replication.
UPDATE1
Here is example of wrapper for default session providers
public class SessionProviderWrapper : SessionStateStoreProviderBase
{
private readonly SessionStateStoreProviderBase _provider;
private static Func<SessionStateStoreProviderBase> _createProvider;
static SessionProvider()
{
_createProvider = InitializerProvider();
}
private static Func<SessionStateStoreProviderBase> InitializerProvider()
{
if (_createProvider != null)
return _createProvider;
var sessionType = "stateserver"; // you can switch to another session provider
Type type;
switch (sessionType)
{
case "inproc":
type = Type.GetType("System.Web.SessionState.InProcSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
break;
case "sql":
type = Type.GetType("System.Web.SessionState.SqlSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
break;
case "stateserver":
type = Type.GetType("System.Web.SessionState.OutOfProcSessionStateStore, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
break;
default:
throw new ConfigurationErrorsException("Unknow session type: " + sessionType);
}
if (type == null)
{
throw new InvalidOperationException("Failed to find session provider for " + sessionType);
}
_createProvider = GenerateConstructorCall(type);
return _createProvider;
}
private static Func<SessionStateStoreProviderBase> GenerateConstructorCall(Type type)
{
// we are searching for public constructor
var constructor = type.GetConstructors().FirstOrDefault(c => c.GetParameters().Length == 0);
if (constructor == null)
{
// otherwise for internal. SQL session provider has internal constructor, but we don't care
constructor = type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(c => c.GetParameters().Length == 0);
}
var node = Expression.New(constructor);
var lambda = Expression.Lambda<Func<SessionStateStoreProviderBase>>(node, null);
var func = lambda.Compile();
return func;
}
public SessionProvider()
{
var createProvider = InitializerProvider();
_provider = createProvider();
}
public override void Initialize(string name, NameValueCollection config)
{
_provider.Initialize(name, config);
}
public override string Name
{
get { return _provider.Name; }
}
public override string Description
{
get { return _provider.Description; }
}
public override void Dispose()
{
_provider.Dispose();
}
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
{
return _provider.SetItemExpireCallback(expireCallback);
}
public override void InitializeRequest(HttpContext context)
{
_provider.InitializeRequest(context);
}
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId,
out SessionStateActions actions)
{
try
{
return _provider.GetItem(context, id, out locked, out lockAge, out lockId, out actions);
}
catch (Exception ex)
{
locked = false;
lockAge = TimeSpan.Zero;
lockId = null;
actions = SessionStateActions.None;
// log ex
return new SessionStateStoreData(new SessionStateItemCollection(), new HttpStaticObjectsCollection(), 10);
}
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId,
out SessionStateActions actions)
{
return _provider.GetItemExclusive(context, id, out locked, out lockAge, out lockId, out actions);
}
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
{
_provider.ReleaseItemExclusive(context, id, lockId);
}
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
_provider.SetAndReleaseItemExclusive(context, id, item, lockId, newItem);
}
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
_provider.RemoveItem(context, id, lockId, item);
}
public override void ResetItemTimeout(HttpContext context, string id)
{
_provider.ResetItemTimeout(context, id);
}
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
{
return _provider.CreateNewStoreData(context, timeout);
}
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
_provider.CreateUninitializedItem(context, id, timeout);
}
public override void EndRequest(HttpContext context)
{
_provider.EndRequest(context);
}
}
Basically you can make try\catch on each method like in GetItem method, and in case of error, you can return empty session object. If it fails in try\catch application still will be alive. But performance will be decreased as for each request it will throw a couple of exceptions on Get\Release, that will be handled in catch section. But anyway these exceptions will decrease performance a bit
I would like to accept tgolisch answer as a solution that works for me.
In Global.asax we will look for the missing StateServer error in the Application_Error event
If we find it we will use Server.ClearError() and log the error
We will also use this to log the error and possibly send out an alert
Thanks all!
I have a asp.net client web application and a WCF web service which was developed from schema xsd. When calling the service i get an error in deserializing body of request. I tried updating service reference but that did not help.
This is my code:
OSEOP.HMA_OrderingBindingClient client = new OSEOP.HMA_OrderingBindingClient();
OSEOP.GetCapabilitiesRequest request = new OSEOP.GetCapabilitiesRequest();
request.GetCapabilities = new OSEOP.GetCapabilities();
request.GetCapabilities.service = "OS";
string[] arrAcceptedVersions = { "1.0.0", "2.0.0" };
request.GetCapabilities.AcceptVersions = arrAcceptedVersions;
OSEOP.Capabilities capabilities = client.GetCapabilities(request.GetCapabilities);
txtGetCapabilitiesResponse.Text = capabilities.Contents.ToString();
client.Close();
and this is the error:
System.ServiceModel.FaultException`1 was unhandled by user code
Message=Error in deserializing body of request message for operation 'GetCapabilities'.
Source=mscorlib
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at OSEOP.HMA_OrderingBinding.GetCapabilities(GetCapabilitiesRequest request)
at OSEOP.HMA_OrderingBindingClient.OSEOP.HMA_OrderingBinding.GetCapabilities(GetCapabilitiesRequest request) in c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\oseop_testclient\023fa9f5\ea876945\App_WebReferences.k9c5tqe1.0.cs:line 44135
at OSEOP.HMA_OrderingBindingClient.GetCapabilities(GetCapabilities GetCapabilities1) in c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\oseop_testclient\023fa9f5\ea876945\App_WebReferences.k9c5tqe1.0.cs:line 44141
at _Default.cmdGetCapabilities_Click(Object sender, EventArgs e) in d:\Documents\DEV\SARPilot\SVN_repository\Services\OrderingServices\TestClient\Default.aspx.cs:line 30
at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:
as you can see, the error happens at the client and never gets sent out to the WCF service. For this reason i'm not getting anything in my MessageLogging. That's why i thought it would have something to do with the service reference.
Can anyone help?
EDIT #1:
What i don't understand is the GetCapabilities takes a GetCapabilitiesRequest parameter but when i'm implementing the client, my intellisense asks for a OSEOP.GetCapabilities object.
OSEOP is what i named the web reference.
public class OrderingService : HMA_OrderingBinding
{
public GetCapabilitiesResponse GetCapabilities(GetCapabilitiesRequest request)
{
throw new NotImplementedException();
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://www.opengis.net/oseop/1.0", ConfigurationName = "HMA_OrderingBinding")]
public interface HMA_OrderingBinding
{
[OperationContract]
[XmlSerializerFormatAttribute]
GetCapabilitiesResponse GetCapabilities(GetCapabilitiesRequest request);
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.2152")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.opengis.net/oseop/1.0")]
public partial class Capabilities : CapabilitiesBaseType
{
private OrderingServiceContentsType contentsField;
private NotificationProducerMetadataPropertyType notificationsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public OrderingServiceContentsType Contents
{
get
{
return this.contentsField;
}
set
{
this.contentsField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 1)]
public NotificationProducerMetadataPropertyType Notifications
{
get
{
return this.notificationsField;
}
set
{
this.notificationsField = value;
}
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(IsWrapped = false)]
public partial class GetCapabilitiesRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.opengis.net/oseop/1.0", Order = 0)]
public GetCapabilities GetCapabilities;
public GetCapabilitiesRequest()
{
}
public GetCapabilitiesRequest(GetCapabilities GetCapabilities)
{
this.GetCapabilities = GetCapabilities;
}
}
EDIT #2 #Marc:
Marc, your answer was very helpful. But you see how the server side is something like this:
GetCapabilitiesResponse GetCapabilities(GetCapabilitiesRequest request)
Yet my intellisense thinks it's something like this:
Capabilities GetCapabilities(GetCapabilities GetCapabilities1)
And I've found a snippet of code within the IOrder.cs file (47,256 lines of code generated from schema) that I'm sure is causing the problem but I tried commenting out the trouble function, updating service reference, and my intellisense still wants GetCapabilities GetCapabilities1
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class HMA_OrderingBindingClient : System.ServiceModel.ClientBase<HMA_OrderingBinding>, HMA_OrderingBinding
{
public HMA_OrderingBindingClient()
{
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
GetCapabilitiesResponse HMA_OrderingBinding.GetCapabilities(GetCapabilitiesRequest request)
{
return base.Channel.GetCapabilities(request);
}
public Capabilities GetCapabilities(GetCapabilities GetCapabilities1)
{
GetCapabilitiesRequest inValue = new GetCapabilitiesRequest();
inValue.GetCapabilities = GetCapabilities1;
GetCapabilitiesResponse retVal = ((HMA_OrderingBinding)(this)).GetCapabilities(inValue);
return retVal.Capabilities;
}
}
Two questions:
Why do you create a GetCapabilitiesRequest object which contains a subobject GetCapabilities, and then in your method call, you only use the contained suboject GetCapabilities??
So why not just create the GetCapabilities in the first place and forget about the wrapping object??
Also, can you please show us the GetCapabilitiesRequest and GetCapabilities and the return class Capabilities, too? If you have a deserialization error, most likely something with those classes isn't right...
Update: thanks for the update to your question....
hmm... can't seem to find anything obviously wrong at first glance....
About your question:
What I don't understand is the
GetCapabilities takes a
GetCapabilitiesRequest parameter but
when I'm implementing the client, my
intellisense asks for a
OSEOP.GetCapabilities object.
Yes, that's clear - your service-side uses its set of classes - GetCapabilitiesRequest and so forth.
When you do an Add Service Reference in Visual Studio, what VS does is
interrogate the server to find out about the service - what methods it has and what parameters it needs
it creates a set of copies of your classes for the client-side proxy - in that namespace that you define on the Add Service Reference dialog box. Those are classes that look exactly the same as your server side classes - but they are not the same classes - they just serialize to XML (and deserialize from XML) the same way as those on the server. That's why your client-side proxy has different classes in a different namespace. That's standard WCF behavior - nothing to be alarmed about...
Update no. 2: Carlos, the schema you sent me seems to be incomplete or has errors. Try to use OGC project on CodePlex as a base and build in your code manually or wait until the schema gets ‘officially’ published.