locked
Strange behavior using global variables in Web API Controller for LS app RRS feed

  • Question

  • Hi,

    I've succesfully created a Web API controller with 3 methods, which return the count of records using different queries. The queries use current user info, such as Member (Miembro in Spanish) stored in a Users entity (Usuarios). The Current User Member Id is retrieved using a Global method as described here.

    The ApiController is invoked when the start screen is created, in order to display the counters (similar to an Issues App where the logged in user has at first sight the number of issues for different issue-states: new, in progress, finished).

    When the page first loads, this error is thrown:

    Microsoft.LightSwitch.DataServiceOperationException was unhandled by user code HResult=-2146233088 Message=The expression is not supported.

    Expression: value(System.Data.Objects.ObjectQuery`1[LightSwitchApplication.Implementation.Usuario]).MergeAs(AppendOnly).Where(persons => (persons.Login == Application.Current.User.Name)).Take(1) Source=Microsoft.LightSwitch StackTrace: at Microsoft.LightSwitch.Framework.Base.ExecutableObject.Execute(Boolean allowJoin) at Microsoft.LightSwitch.Framework.Base.ExecutableObject.Execute() at Microsoft.LightSwitch.Framework.Base.ExecutableObject`1.Execute() at Microsoft.LightSwitch.ServerGenerated.Implementation.QueryImplementation`1.GetEnumerator() at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext() at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source) at Microsoft.LightSwitch.DataServiceQueryable.<FirstOrDefault>b__1[TSource](IEnumerable`1 e) at Microsoft.LightSwitch.DataServiceQueryable.ScalarImpl[T](IDataServiceQueryable`1 source, Int32 takeCount, Func`2 scalarFunction) at Microsoft.LightSwitch.DataServiceQueryable.FirstOrDefault[TSource](IDataServiceQueryable`1 source) at LightSwitchApplication.Globals.LoggedOnPerson() at LightSwitchApplication.Globals.CurrentUserMemberId() at LightSwitchApplication.Controllers.IndicadoresS3InicioController.IncidentesTotal() at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass13.<GetExecutor>b__c(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c__DisplayClass5.<ExecuteAsync>b__4() at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken) ...


    When calling LoggedOnPerson():

    public class Globals
    {
            public static int CurrentUserId()
            {
                Usuario person = LoggedOnPerson();
                return person != null ? person.Id : -1;
            }
    
            public static int CurrentUserMemberId()
            {
                Usuario person = LoggedOnPerson();
                return person != null ? person.Miembro.Id : -1;
            }
    
            private static Usuario LoggedOnPerson()
            {
                return (from persons in Application.Current.CreateDataWorkspace().ApplicationData.Usuarios
                        where persons.Login == Application.Current.User.Name
                        select persons).FirstOrDefault();
            }
    }

    The strange behavior is: the error is thrown only the first time the function is called, and it is called 3 times overall. Plus, if I hit refresh (F5), the start page loads with all 3 counters correctly calculated, with no errors.

    I'm open to suggestions and other approaches to the problem of "generating indicators using current user info and Web API Controllers".

    Finally, I've been using the public methods in Globals in many queries without any problems, and the Controller is in the LightSwitchApplication namespace as well. Also, I tried retrieving the current user info in the same context and DataworkSpace as the Controller, but the result is the same.



    Wednesday, July 2, 2014 11:31 PM

Answers

  • I replaced Globals.CurrentUserMemberId() with a query within the Controller's context that returns the Current Member Id, problem solved.

    Nicolás Lope de Barrios
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Tuesday, July 15, 2014 5:37 PM

All replies

  • More info:

    Sometimes, even after rebuilding all, I get no errors. Other times, after "Expression is not supported", when I hit Continue, I get this one:

    An exception of type 'System.InvalidOperationException' occurred in System.Core.dll but was not handled in user code

    Additional information: Sequence contains no matching element

    On this auto generated code (EntityG17.cs):

    public global::LightSwitchApplication.Miembro Miembro
            {
                get
                {
                    return global::LightSwitchApplication.Usuario.DetailsClass.GetValue(this, global::LightSwitchApplication.Usuario.DetailsClass.PropertySetProperties.Miembro);
                }
                set
                {
                    global::LightSwitchApplication.Usuario.DetailsClass.SetValue(this, global::LightSwitchApplication.Usuario.DetailsClass.PropertySetProperties.Miembro, value);
                }
            }

    HTH.

    Wednesday, July 2, 2014 11:38 PM
  • The strange behavior is: the error is thrown only the first time the function is called, and it is called 3 times overall. Plus, if I hit refresh (F5), the start page loads with all 3 counters correctly calculated, with no errors.

    According to your description above, here are some suggestions for you.

    try restarting Visual Studio (and even your local machine)

    Cleaning and rebuilding your current Project.

    Set breakpoint to monitor the process.

    Please check whether it can give some hints why this happens.

    Regards


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, July 11, 2014 2:21 PM
  • You could verify that Application.Current.User.Name has a value before calling the query. Maybe during the page initialization Application.Current.User is not yet available?

    Paul

    Sunday, July 13, 2014 1:51 PM
  • Maybe during the page initialization Application.Current.User is not yet available?

    Paul

    That's what I think is happening. I will try to change when the controller is called, check if the page is loaded first. Thank you.


    Nicolás Lope de Barrios
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Sunday, July 13, 2014 2:04 PM
  • I replaced Globals.CurrentUserMemberId() with a query within the Controller's context that returns the Current Member Id, problem solved.

    Nicolás Lope de Barrios
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Tuesday, July 15, 2014 5:37 PM