locked
Custom method not working anymore (since RIA July) RRS feed

  • Question

  • I have a method on my DomainService which is marked with the CustomAttribute:

     

    [Custom]
    public void SomeCustomOperation(CustomerEntity entity, bool someParameter)
    {
       if (someParameter)
          entity.Name = entity.Name.ToLower();
       else
          entity.Name = entity.Name.ToUpper();
    }
    

     

    Note that in the real scenario we would do some business logic operation of course.
    I have a button in my Silverlight page to invoke the custom operation:

    private void _someCustomOperation_Click(object sender, RoutedEventArgs e)
    {
       CustomerEntity customer = (CustomerEntity)(_customerView.CurrentItem);
       customer.SomeCustomOperation( _upperCaseSwitch );
       _upperCaseSwitch = !_upperCaseSwitch;
    
       // Have to submit changes for custom operations to take effect! 
       _ctx.SubmitChanges();
    }
    

    This code worked fine with the RIA May version. With the July version I have two problems:

    • the first time I click the button, the event is invoked via the generated client side entity. But the event never invokes the server side domain service. When I check with Fiddler, I don't see a request either.
    • the second time I click the button, I see an "A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.Ria" in the Output window and the browser screen show a blank screen. Navigating back won't recover the screen only a refresh will. 

    The DomainDataSource is bound to a DataGrid and the currently selected item in the grid, the current customer, is bound to a DataForm with a ReadOnlyTemplate and an EditTemplate.

    I have also tried replacing the "_ctx.SubmitChanges()" call with the direct SubmitOperation like this:

    CustomerDomainService service = _ctx.DomainContext as CustomerDomainService;
    SubmitOperation op = service.SubmitChanges();
    
     

     

    But that didn't change anything. Why would it, since the DomainDataSource is doing the same thing after all. Any ideas why this functionality is broken?
    Wednesday, August 5, 2009 8:07 AM

Answers

  • Maybe I misread, but I thought it might be important to emphasize that the DDS SubmitChanges is not synchronous. Actually, it more-or-less delegates to _ctx.DomainContext.SubmitChanges. The two synch/async options you have above are pretty much identical. There are only a couple minor differences. The DDS version uses the async event pattern (with a SubmittedChanges event) and will invoke Load() immediately after successful completion while the other version is standard DomainContext behavior.

    Kyle

    Wednesday, August 5, 2009 11:06 AM

All replies

  • Maybe I misread, but I thought it might be important to emphasize that the DDS SubmitChanges is not synchronous. Actually, it more-or-less delegates to _ctx.DomainContext.SubmitChanges. The two synch/async options you have above are pretty much identical. There are only a couple minor differences. The DDS version uses the async event pattern (with a SubmittedChanges event) and will invoke Load() immediately after successful completion while the other version is standard DomainContext behavior.

    Kyle

    Wednesday, August 5, 2009 11:06 AM
  • Maybe I misread, but I thought it might be important to emphasize that the DDS SubmitChanges is not synchronous.

    Yes, you are of course right about that. I forgot about the DDS events that are published, since I expected the DDS SubmitChanges to return a SubmitOperation as well, which you could subscribe to. This put me on the wrong track and made me assume is was a blocking call....

    Wednesday, August 5, 2009 11:31 AM
  • Just to follow up, there haven't been any other reports of issues with Custom methods in the July release. It would be interesting to know what your code is doing and what exceptions you're seeing to track down any issues that might be hidden in the framework.

    Kyle

    Thursday, August 13, 2009 10:23 AM
  • It's a very simple scenario with a POCO entity. When I press the button to invoke the custom operation, I don't get any exception. The debugger doesn't break in the domain service, so I assume that the domain service is not called and something is wrong in the client. When I press the button once more I get an exception:

    {System.InvalidOperationException: Only one pending domain method invocation is allowed per entity.
       at System.Windows.Ria.Data.Entity.InvokeAction(String actionName, Object[] parameters)}

    The button is part of the DataForm and the DataForm is linked via code to a DataGrid. I also had a custom validation attribute on the property and that one was called when I pressed the button. The custom operation changes the property from lowercase to uppercase or the other way around. When I remove the custom validation attribute from the property, it still doesn't work.

    Thursday, August 13, 2009 1:16 PM
  • Maybe I misread, but I thought it might be important to emphasize that the DDS SubmitChanges is not synchronous.

    Now I see how I came to the conclusion of the DDS.SubmitChanges being a synchronous operation: intellisense tooltip tells me:

    void DomainDataSource.SubmitChanges() 
       Starts a submit operation synchronously

    Thursday, August 13, 2009 1:34 PM
  • I have found the cause for the problem:

    - my entity has another a property tagged with a StringLength-constraint.

    - I use a SqlDataReader and that didn't trim trailing space when loading my POCO. So it loaded something like "VALUE             " and I have a string constraint of 10 characters

    - the initial version of the entity was loaded with a property value that was too long, so the initial state is invalid.

    - there are no error indicators when the DataGrid displays the entity, nor in the DataForm

    - when I invoke the custom operation via the DDS, the validation is triggered and probably cancels the Custom operation

    - I assume the internal domain context state isn't healthy after this scenario, since now it thinks it still has a pending operation. You will see this when invoked the custom operation once more

    I was finally able to see the error when invoking the custom operation on the domain context instead of the DDS. I'm sure I tested that before.... probably not. Anyway the error indicators to show validation issues are not visualized, which is misleasing in this case.

    Thursday, August 13, 2009 1:55 PM
  • In general the scenario is: when your entity has a broken validation constraint, calling a custom or service operation will change the domain context in an unstable state. A reload of the page is the only thing that helps.

    Thursday, August 13, 2009 2:12 PM
  • Thanks Theo. I'll write a bug up for it.

    Kyle

    Thursday, August 13, 2009 4:23 PM
  • There is for sure a bug in RIA Services July. I've the same problem. My Custom Method compiles fine.
    But when I run it, NOTHING happens, not even a error. That's really terrible! I really need this Custom Method.

    Friday, August 21, 2009 4:35 AM
  • See http://silverlight.net/forums/t/121359.aspx for a possible solution/cause...

    Friday, August 21, 2009 7:45 AM
  • Thank you, Theo

    Friday, August 21, 2009 9:30 AM
  • Hi there,

    I'm having the exact same symtops as the topic starter. When I call my method for the first time it look likes my custom method does nothing. The second time on that I call the method on the same entitiy it results in the error: A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.Ria

    I new to Silverlight and the .NET Ria Services, I read the Microsoft .NET Ria Services overview document and it should be working. So what am I doing wrong?

    This is what I have so far:

    A DomainService bases on L2S wich contains the usual Get, Insert, Update and Delete methods of a entities called Question and Result.
    In the DomainService I also declared the following custom method:

     

    [Custom]
    public void GiveAnswer(Question question, string answer, string comment)
    {
       Context.Questions.Attach(question);
       Result result = new Result {
             QuestionId = question.QuestionId, 
             Answer = answer, 
             Comment = comment
       };
    
    // Some calculations with result
    
       Context.Results.InsertOnSubmit(result);   
       Context.SubmitChanges();
    }

     

    This code allows me to call in _question.GiveAnswer("this is the right answer", "No its not") my client project. When the debugger hits this line for the first time it does not throwing an error. The second time it throws the error earlier mentioned. The entities are generated from LinQ2Sql classes, including the metadata files, although i didn't do anything with those yet.

     

    Monday, December 7, 2009 5:26 PM