Breeze: cannot execute _executeQueryCore until metadataStore is populated - metadata

I was using Breeze v1.1.2 that came with the Hot Towel template which has now been extended to form my project. I made the mistake of updating the NuGet package to the current 1.3.3 (I never learn). Anyway, all was well, and now not so much!
I followed the instructions in the release notes and other docs to change my BreezeWebApiConfig file to:
[assembly: WebActivator.PreApplicationStartMethod(
typeof(BreezeWebApiConfig), "RegisterBreezePreStart")]
namespace MyApp.App_Start {
public static class BreezeWebApiConfig {
public static void RegisterBreezePreStart() {
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "BreezeApi",
routeTemplate: "breeze/{controller}/{action}"
);}}}
And the config.js file (which provides the serviceName to the EntityManager constructor) to:
var remoteServiceName = 'breeze/breeze'; // NEW version
//var remoteServiceName = 'api/breeze'; // OLD version
And my BreezeController if you're interested:
[BreezeController]
public class BreezeController : ApiController
{
readonly EFContextProvider<MyDbContext> _contextProvider =
new EFContextProvider<MyDbContext>();
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
[HttpGet]
public IQueryable<SomeItem> SomeItems()
{
// Do stuff here...
}
}
Now I get the "cannot execute _executeQueryCore until metadataStore is populated" error.
What am I missing here?
EDIT:
I perhaps left out the part you needed... Above in the SomeItems() method, the stuff that actually gets done is a call to the GetMeSomeData() method in the MyDBContext class. This method makes the following call to a stored procedure to get the data.
public virtual ObjectResult<SomeItem> GetMeSomeData(string inParam)
{
var p = new object[] { new SqlParameter("#inParam", inParam) };
var retVal = ((IObjectContextAdapter)this).ObjectContext.ExecuteStoreQuery<SomeItem>("exec GetData #SN", p);
return retVal;
}
Now given my limited understanding, the call to Metadata() is not failing, but I don't think it has any idea what the entity model is when coming back, even though somewhere along the line, it should figure that out from the entity model I do have (i.e. SomeItem)? The return string from Metadata() doesn't have any information about the entity. Is there a way to make it aware? Or am I just completely off in left field playing with the daisies?

Hard to say based on this report. Let's see if Breeze is right.
Open the browser debugging tools and look at the network traffic. Do you see an attempt to get metadata from the server before you get that error? If so, did it succeed? Or 404? Or 500? What was the error?
I'm betting it didn't even try. If it didn't, the usual reason is that you tried some Breeze operation before your first query ... and you didn't ask for metadata explicitly either. Did you try to create an entity? That requires metadata.
The point is, you've got to track down the Breeze operation that precipitates the error. Sure everything should just work. The world should be rainbows and unicorns. When it isn't, we heave a sigh, break out the debugger, and start with the information that the error gave us.
And for the rest of you out there ... upgrading to a new Breeze version is a good thing.
Happy coding everyone.
Follow-up to your update
Breeze doesn't know how you get your data on the back-end. If the query result has a recognizable entity in it, Breeze will cache that. It's still up to you in the query callback to ensure that what you deliver to the caller is something meaningful.
You say that you're server-side metadata method doesn't have any idea what SomeItem is? Then it's not much use to the client. If it returns a null string, Breeze may treat that as "no metadata at all" in which case you should be getting the "cannot execute _executeQueryCore until metadataStore is populated" error message. Btw, did you check the network traffic to determine what your server actually returned in response to the metadata request (or if there was such a request)?
There are many ways to create Metadata on the server. The easiest is to use EF ... at least as a modeling tool at design time. What's in that MyDbContext of yours? Why isn't SomeItem in there?
You also can create metadata on the client if you don't want to generate it from the server. You do have to tell the Breeze client that you've made that choice. Much of this is explained in the documentation "Metadata Format".
I get the feeling that you're kind of winging it. You want to stray from the happy path ... and that's cool. But most of us need to learn to walk before we run.

Related

Stored Procedure returns old value in ef core

I have an ASP.NET Core Web API. I am using raw SQL with a stored procedure to compute some values:
private TestContext context;
public TestRepository(TestContext tContext)
{
context = tContext;
}
public IEnumerable<test> GetTests(User user)
{
return context.tests.FromSql("EXECUTE dbo.test_GETALL {0}", user.code).ToList();
}
When I insert new record into my table, the result must be changed, but this code returns old values. How I fix this problem?
If TestContext is connected to EF, than that's the problem, or otherwise you may have your transaction badly configured.
I had a similar problem to this myself.
Check your startup.cs and make sure that service and repositories are not .AddSingleton.
These will need to be changed to .AddScoped (You might be able to use .AddTransient too)
services.AddSingleton<IYourService, YourService>(); //Needs to be AddScoped
services.AddSingleton<IYourRepository, YourRepository>(); //Also needs to be AddScoped
If you need more detail, here is my SO question that I believe relates to your situation.
Hope this helps!

Enforce Hyphens in .NET MVC 4.0 URL Structure

I'm looking specifically for a way to automatically hyphenate CamelCase actions and views. That is, I'm hoping I don't have to actually rename my views or add decorators to every ActionResult in the site.
So far, I've been using routes.MapRouteLowercase, as shown here. That works pretty well for the lowercase aspect of URL structure, but not hyphens. So I recently started playing with Canonicalize (install via NuGet), but it also doesn't have anything for hyphens yet.
I was trying...
routes.Canonicalize().NoWww().Pattern("([a-z0-9])([A-Z])", "$1-$2").Lowercase().NoTrailingSlash();
My regular expression definitely works the way I want it to as far as restructuring the URL properly, but those URLs aren't identified, of course. The file is still ChangePassword.cshtml, for example, so /account/change-password isn't going to point to that.
BTW, I'm still a bit rusty with .NET MVC. I haven't used it for a couple years and not since v2.0.
This might be a tad bit messy, but if you created a custom HttpHandler and RouteHandler then that should prevent you from having to rename all of your views and actions. Your handler could strip the hyphen from the requested action, which would change "change-password" to changepassword, rendering the ChangePassword action.
The code is shortened for brevity, but the important bits are there.
public void ProcessRequest(HttpContext context)
{
string controllerId = this.requestContext.RouteData.GetRequiredString("controller");
string view = this.requestContext.RouteData.GetRequiredString("action");
view = view.Replace("-", "");
this.requestContext.RouteData.Values["action"] = view;
IController controller = null;
IControllerFactory factory = null;
try
{
factory = ControllerBuilder.Current.GetControllerFactory();
controller = factory.CreateController(this.requestContext, controllerId);
if (controller != null)
{
controller.Execute(this.requestContext);
}
}
finally
{
factory.ReleaseController(controller);
}
}
I don't know if I implemented it the best way or not, that's just more or less taken from the first sample I came across. I tested the code myself so this does render the correct action/view and should do the trick.
I've developed an open source NuGet library for this problem which implicitly converts EveryMvc/Url to every-mvc/url.
Uppercase urls are problematic because cookie paths are case-sensitive, most of the internet is actually case-sensitive while Microsoft technologies treats urls as case-insensitive. (More on my blog post)
NuGet Package: https://www.nuget.org/packages/LowercaseDashedRoute/
To install it, simply open the NuGet window in the Visual Studio by right clicking the Project and selecting NuGet Package Manager, and on the "Online" tab type "Lowercase Dashed Route", and it should pop up.
Alternatively, you can run this code in the Package Manager Console:
Install-Package LowercaseDashedRoute
After that you should open App_Start/RouteConfig.cs and comment out existing route.MapRoute(...) call and add this instead:
routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
new DashedRouteHandler()
)
);
That's it. All the urls are lowercase, dashed, and converted implicitly without you doing anything more.
Open Source Project Url: https://github.com/AtaS/lowercase-dashed-route
Have you tried working with the URL Rewrite package? I think it pretty much what you are looking for.
http://www.iis.net/download/urlrewrite
Hanselman has a great example herE:
http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx
Also, why don't you download something like ReSharper or CodeRush, and use it to refactor the Action and Route names? It's REALLY easy, and very safe.
It would time well spent, and much less time overall to fix your routing/action naming conventions with an hour of refactoring than all the hours you've already spent trying to alter the routing conventions to your needs.
Just a thought.
I tried the solution in the accepted answer above: Using the Canonicalize Pattern url strategy, and then also adding a custom IRouteHandler which then returns a custom IHttpHandler. It mostly worked. Here's one caveat I found:
With the typical {controller}/{action}/{id} default route, a controller named CatalogController, and an action method inside it as follows:
ActionResult QuickSelect(string id){ /*do some things, access the 'id' parameter*/ }
I noticed that requests to "/catalog/quick-select/1234" worked perfectly, but requests to /catalog/quick-select?id=1234 were 500'ing because once the action method was called as a result of controller.Execute(), the id parameter was null inside of the action method.
I do not know exactly why this is, but the behavior was as if MVC was not looking at the query string for values during model binding. So something about the ProcessRequest implementation in the accepted answer was screwing up the normal model binding process, or at least the query string value provider.
This is a deal breaker, so I took a look at default MVC IHttpHandler (yay open source!): http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs
I will not pretend that I grok'ed it in its entirety, but clearly, it's doing ALOT more in its implementation of ProcessRequest than what is going on in the accepted answer.
So, if all we really need to do is strip dashes from our incoming route data so that MVC can find our controllers/actions, why do we need to implement a whole stinking IHttpHandler? We don't! Simply rip out the dashes in the GetHttpHandler method of DashedRouteHandler and pass the requestContext along to the out of the box MvcHandler so it can do its 252 lines of magic, and your route handler doesn't have to return a second rate IHttpHandler.
tl:dr; - Here's what I did:
public class DashedRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.RouteData.Values["action"] = requestContext.RouteData.GetRequiredString("action").Replace("-", "");
requestContext.RouteData.Values["controller"] = requestContext.RouteData.GetRequiredString("controller").Replace("-", "");
return new MvcHandler(requestContext);
}
}

Update a table using JPA in Play Framework

I'm trying to update a table using JPA
EntityManager em=JPA.em();
EntityTransaction entr = em.getTransaction();
try{
if(!entr.isActive())
entr.begin();
Tblrecordtypefields updateTblrecordtypes = em.find(Tblrecordtypefields.class,9);
updateTblrecordtypes.setFieldlabel("JPATest");
em.getTransaction().commit();
}finally
{
if(entr.isActive())
entr.rollback();
}
i'm getting the error
NullPointerException occured : null at
updateTblrecordtypes.setFieldlabel("JPATest");
What should i do.
I see some possible issues in there:
First, Play manages the transactions on it's own. A transaction is created at the beginning of the request and committed (rollback if exception) at the end. You are trying to force your way into it, that's not recommended. To manage the entity, just do an entity.save() to mark it as "to be saved" and don't do tht to ignore any changes.
Second, if you are using the Model class in Play (as you should) you can use the "find" and "findById" methods provided by this class. This is recommened, instead of using the EntityManager directly.
See the documentation for more information.
Basically, redo your code to follow the Play way, to avoid problems :)
EDIT: as a clarification, I'm not really answering your question on why you get the NPE, but I think that as you are forcing your way into the settings of the framework you might (maybe not!) be seeing unexpected artifacts that will dissapear once you fix your code to follow convention.
If after that you still have the error let us know :)
This means that there is no row with ID 9 in the database table mapped by the entity Tblrecordtypefields.
BTW: I find it very questionable to commit a transaction in a method which is not necessary the one that started the transaction.
I have changed my code as below
Tblrecordtypefields updateTblrecordtypeFields = Tblrecordtypefields.findById(9);
updateTblrecordtypeFields.setFieldlabel("Test");
validation.valid(updateTblrecordtypeFields);
if(validation.hasErrors())
{
updateTblrecordtypeFields.refresh();
}
else
{
updateTblrecordtypeFields.save();
}
in my model class
public void setFieldlabel(String fieldlabel) {
this.fieldlabel = fieldlabel;
}
Works Fine.....

XML serialization errors when trying to serialize Entity Framework objects

I have entities that I am getting via Entity Framework. I'm using Code-First so they're POCOs. When I try to XML Serialize them using XmlSerializer, I get the following error:
The type
System.Data.Entity.DynamicProxies.Song_C59F4614EED1B7373D79AAB4E7263036C9CF6543274A9D62A9D8494FB01F2127
was not expected. Use the XmlInclude
or SoapInclude attribute to specify
types that are not known statically.
Anybody got any ideas on how to get around this (short of creating a whole new object)?
Just saying POCO doesn't really help (especially in this case since it looks like you're using proxies). Proxies come in handy in a lot of cases but make things like serialization more difficult since the actual object being serialized is not really your object but an instance of a proxy.
This blog post should give you your answer.
http://blogs.msdn.com/b/adonet/archive/2010/01/05/poco-proxies-part-2-serializing-poco-proxies.aspx
Sorry, I know I'm coming at this a bit late (a couple YEARS late), but if you don't need the proxy objects for lazy loading, you can do this:
Configuration.ProxyCreationEnabled = false;
in your Context. Worked like a charm for me. Shiv Kumar actually gives better insight into why, but this at least will get you back to work (again, assuming you don't need the proxies).
Another way that works independent of the database configuration is by doing a deep clone of your object(s).
I use Automapper (https://www.nuget.org/packages/AutoMapper/) for this in my code-first EF project. Here is some sample code that exports a list of an EF objects called 'IonPair':
public bool ExportIonPairs(List<IonPair> ionPairList, string filePath)
{
Mapper.CreateMap<IonPair, IonPair>(); //creates the mapping
var clonedList = Mapper.Map<List<IonPair>>(ionPairList); // deep-clones the list. EF's 'DynamicProxies' are automatically ignored.
var ionPairCollection = new IonPairCollection { IonPairs = clonedList };
var serializer = new XmlSerializer(typeof(IonPairCollection));
try
{
using (var writer = new StreamWriter(filePath))
{
serializer.Serialize(writer, ionPairCollection);
}
}
catch (Exception exception)
{
string message = string.Format(
"Trying to export to the file '{0}' but there was an error. Details: {1}",
filePath, exception.Message);
throw new IOException(message, exception);
}
return true;
}

EF 4 Self Tracking Entities does not work as expected

I am using EF4 Self Tracking Entities (VS2010 Beta 2 CTP 2 plus new T4 generator). But when I try to update entity information it does not update to database as expected.
I setup 2 service calls. one for GetResource(int id) which return a resource object. the second call is SaveResource(Resource res); here is the code.
public Resource GetResource(int id)
{
using (var dc = new MyEntities())
{
return dc.Resources.Where(d => d.ResourceId == id).SingleOrDefault();
}
}
public void SaveResource(Resource res)
{
using (var dc = new MyEntities())
{
dc.Resources.ApplyChanges(res);
dc.SaveChanges();
// Nothing save to database.
}
}
//Windows Console Client Calls
var res = service.GetResource(1);
res.Description = "New Change"; // Not updating...
service.SaveResource(res);
// does not change anything.
It seems to me that ChangeTracker.State is always show as "Unchanged".
anything wrong in this code?
This is probably a long shot... but:
I assume your Service is actually in another Tier? If you are testing in the same tier you will have problems.
Self Tracking Entities (STEs) don't record changes until when they are connected to an ObjectContext, the idea is that if they are connected to a ObjectContext it can record changes for them and there is no point doing the same work twice.
STEs start tracking once they are deserialized on the client using WCF, i.e. once they are materialized to a tier without an ObjectContext.
If you look through the generated code you should be able to see how to turn tracking on manually too.
Hope this helps
Alex
You have to share assembly with STEs between client and service - that is the main point. Then when adding service reference make sure that "Reuse types in referenced assemblies" is checked.
The reason for this is that STEs contain logic which cannot be transfered by "Add service reference", so you have to share these types to have tracing logic on client as well.
After reading the following tip from Daniel Simmons, the STE starts tracking. Here is the link for the full article. http://msdn.microsoft.com/en-us/magazine/ee335715.aspx
Make certain to reuse the Self-Tracking Entity template’s generated entity code on your client. If you use proxy code generated by Add Service Reference in Visual Studio or some other tool, things look right for the most part, but you will discover that the entities don’t actually keep track of their changes on the client.
so in the client make sure you don't use add service reference to get the proxy instead access service through following code.
var svc = new ChannelFactory<IMyService>("BasicHttpBinding_IMyService").CreateChannel();
var res = svc.GetResource(1);
If you are using STEs without WCF you may have to call StartTracking() manually.
I had the same exact problem and found the solution.
It appears that for the self-tracking entities to automatically start tracking, you need to reference your STE project before adding the service reference.
This way Visual Studio generates some .datasource files which does the final trick.
I found the solution here:
http://blogs.u2u.be/diederik/post/2010/05/18/Self-Tracking-Entities-with-Validation-and-Tracking-State-Change-Notification.aspx
As for starting the tracking manually, it seems that you do not have these methods on the client-side.
Hope it helps...