0
votes

Within my project I am trying to perform a save operation that updates my Breeze model as well as passes the updated object to my webAPI. In this project I am not using EF context as the project has been modeled to work with other interfaces. So within my webAPI class I have the following:

  [BreezeController]
    public class ReportLibraryApiController : ApiController
    {
       readonly long userid = 1;//testing
       readonly IReportLibraryManager manager = new ReportLibraryManager();//interface 

        //method for share
        [Route("reportlibrary/SetReportShare/")]
        [HttpPost]
        public DTOs.Report SetReportShare(JObject report )
        {
             //within here I plan to unwrap the JSobject and pull out the necessary 
             //fields that I need 
            DTOs.Report updatedreport=null;

            //manager.ShareReport(updatedreport.ReportId);
            //manager.UnShareReport(updatedreport.ReportId);
            return updatedreport;
        }
}

The Report Object looks like this

public class Report
{

    public Int64 ReportId { get; set; }
    public string ReportName { get; set; }
    public string ReportDescription { get; set; }
    public DateTime? ReportDateCreated { get; set; }
    public string ReportOwner { get; set; }
    public IEnumerable<ReportLabel> ReportLabels { get; set; }
    public bool IsShared { get; set; }
    public bool IsFavorite { get; set; }
}

From my angular service I am trying to call the save operation as:

app.factory('reportLibraryService',  function(breeze,  model){

        var serviceName = "reportlibrary/";

        var ds = new breeze.DataService({
            serviceName: serviceName,
            hasServerMetadata: false,
            useJsonp: true,

        });

        var manager = new breeze.EntityManager({ dataService: ds });

        model.initialize(manager.metadataStore);

        function returnResults(data){ return data.results}

        function setReportShare(report) {
           var option = new breeze.SaveOptions({ resourceName: 'SetReportShare' })
           return  manager.saveChanges(null, option).then(returnResults)
        };
}

I realize the return results may not be correct but at this point I am just trying to call the save operation in the API. When I run the code everything executes but the save/setting of the share does not fire. A secondary question is I'm still not clear on how the breeze model is updated? Am I supposed to issue a new query from the api and pass that back or is there a way to update the cached object. I'm new to breeze (obviously) and trying to figure out where to look.All the examples I have seen thus far use EF context to perform these actions. However in my case I don't have that option.

Should breeze be making the call or since I am not using EF should I be using $http directive to push the object up. then return a new object to breeze for binding? (that seems a little heavy to me and now how it is designed to work). I'd appreciate any guidance, or information or how to figure this out.

Edited for more information... Here is a little more detail based on some of the questions posted by Ward to my original question:

where is your metadata that you code says is not on the server?

The solution I am working on does not expose the EF context this far our. As a result interfaces have been created that handle the queries etc within the project. As a result I don't have the ability to use EF. Very similar to the Edmunds sample. I created a meta definition in the web project which references a report object I have defined. This class is much different from what is returned from the DB but it represents what the UI needs. I created two models

report.cs

public class Report {

public Int64 ReportId { get; set; }
public string ReportName { get; set; }
public string ReportDescription { get; set; }
public DateTime? ReportDateCreated { get; set; }
public string ReportOwner { get; set; }
public IEnumerable<ReportLabel> ReportLabels { get; set; }
public bool IsShared { get; set; }
public bool IsFavorite { get; set; }

}

model.js

app.factory('model', function () {

    var DT = breeze.DataType;
    return {
        initialize: initialize
    }

    function initialize(metadataStore) {
        metadataStore.addEntityType({
            shortName: "Report",
            namespace: "Inform.UI.DTOs",
            dataProperties: {
                reportId: { dataType: DT.Int64, isPartOfKey: true },
                reportName: { dataType: DT.String },
                reportDescription: { dataType: DT.String },
                reportDateCreated: { dataType: DT.String },
                reportOwner: { dataType: DT.String },
                reportLabels: { dataType: DT.Undefined },
                isShared: { dataType: DT.Bool },
                isFavorite: { dataType: DT.Bool }
            },
            navigationProperties: {
                labels: {
                    entityTypeName: "Label:#Inform.UI.DTOs", isScalar: false,
                    associationName: "Report_Labels"
                }
            }
        });
        metadataStore.addEntityType({
            shortName: "ReportLabel",
            namespace: "Inform.UI.DTOs",
            dataProperties: {
                labelId: { dataType: DT.Int64, isPartOfKey: true },
                reportId: { dataType: DT.Int64 },
                labelName: { dataType: DT.String },
                isPublic: { dataType: DT.Bool },
                reports: { dataType: DT.Undefined }
            },
            navigationProperties: {
                labels: {
                    entityTypeName: "Report:#Inform.UI.DTOs", isScalar: false,
                    associationName: "Report_Labels", foreignKeyNames: ["reportId"]
                }
            }
        });
    }
})

why are you configuring useJsonp = true ... and then POSTing to the SetReportShare endpoint?

The dataservice was originally defined for GET requests for querying/returning results to the client. I reused the dataservice and tacked on the POST event. Based on your comment though I assume this is a no-no. In looking at the project I am working within the same domain (and always will be) so I don't really think I need jsonp as part of the dataservice definition. Am I wrong in thinking that? I gather from your question that I should have a separate dataservice for POST's and a separate one for GET's

why is it returning the DTOs.Report type when you can tell by looking at the standard Breeze SaveChanges method that it returns a SaveResult?

This was a typo on my part. The save Result was originally defined as just a JObject. My intent is to return (if necessary) an updated Report object. However I am unsure of the best practice here. If the client (breeze) is updating the cache object. Why do I need to return the report object. Would it not be better to just return a success fail result or boolean of some sort vs. returning an entire report object?

why is your client-side saveChanges callback treating the response as if it came from a query?

This is very simple as you stated, I have no idea what I am doing. I am certainly diving into the deep end as I don't have a choice right now... My question here is when you perform a CRUD operation are these not wrapped in a promise as when performing a query? Or is the promise only important for queries?

Thank you again-

-cheers

1
As I noted in my answer, if you insist on sidestepping EF right from the start, you should look at the NoDb sample which strips things down to essentials. Load it. Play with it. Learn from it. I think it will really help you get on track.Ward

1 Answers

1
votes

You're jumping into the deep end w/o knowing how to swim.

You haven't explained why you're going exotic. That's OK but you want to ease into it. I strongly recommend that you start with the "happy" path - Web API, EF, SQL Server - and then unwind them slowly as you start to understand what's going on.

If you can't do that, at least look at the NoDb sample which doesn't use EF or SQL Server (see the TodoRepository).

You absolutely can do what you're striving to do ... once you know how ... or find someone who does.

At this point, you've created nothing but questions. For example,

  • where is your metadata that you code says is not on the server?

  • why are you configuring useJsonp = true ... and then POSTing to the SetReportShare endpoint?

  • why is it returning the DTOs.Report type when you can tell by looking at the standard Breeze SaveChanges method that it returns a SaveResult?

  • why is your client-side saveChanges callback treating the response as if it came from a query?

As for your questions:

  • the breeze model is updated automatically when the save completes
  • no, you don't issue a new query from the api
  • yes, you can (and usually do) return the server-updated object back in the SaveResult.
  • $http (a method not a directive) is used by Breeze itself to communicate to the server; using it directly isn't going to change anything.

Not sure any of my answers help. But I do think you'll be fine if you take it from the top and work deliberately forward from one thing you understand to the next.