Breeze navigation properties - javascript

I have just started working with Breeze (using Angular) and have managed to get some data from my Odata service and displayed it on the page. However, I now need to get a related field via a foreign key (I need to get Group related to a Team object) and I am having some difficulties. Using datajs after version 1.0.3 causes issues so I am using version 1.0.3, but this version does not allow 'expand' to be used. So instead I have disabled lazy loading in my model and used Include when getting in my controller :
public partial class Team
{
public int TeamId { get; set; }
public string TeamName { get; set; }
public string FlagSmall { get; set; }
public string FlagLarge { get; set; }
public string BadgeSmall { get; set; }
public string BadgeLarge { get; set; }
public string TeamImage { get; set; }
//foreign key
public int GroupId { get; set; }
//navigation properties
public Group Group { get; set; } //virtual removed to disable lazy loading
}
// GET odata/Teams
[Queryable]
public IQueryable<Team> GetTeams()
{
return db.Teams.Include("Groups"); //get navigation property
}
// GET odata/Teams(5)
[Queryable]
public SingleResult<Team> GetTeam([FromODataUri] int key)
{
return SingleResult.Create(db.Teams.Include("Groups").Where(team => team.TeamId == key));
}
However, this does not work either, it gives a similar error to the error caused by > datajs 1.0.3 :
[Q] Unhandled rejection reasons (should be empty): ["createError#http://bras...s/datajs-1.0.3.js:1055\n"]
Has anybody got around this and managed to get related fields via a foreign key?
EDIT :
Here is my angular code, I have tried referring to team.Group.GroupName, team.GroupName, and group.GroupName, but neither of these works :
<tbody>
<tr ng-repeat="team in teams | filter:search:TeamName | orderBy:'TeamId'" id="team_{{team.id}}">
<td>{{team.TeamId}}</td>
<td>{{team.TeamName}}</td>
<td><img src={{team.FlagSmall}}></img></td>
<td><img style="width:40px;height:40px" src={{team.FlagLarge}}></img></td>
<td><img style="width:40px;height:40px" src={{team.BadgeSmall}}></img></td>
<td><img style="width:40px;height:40px" src={{team.BadgeLarge}}></img></td>
<td><img style="width:80px;height:40px" src={{team.TeamImage}}></img></td>
<td>{{team.Group.GroupName}}</td>
</tr>
</tbody>
EDIT 2 :
This is my Breeze query :
this.basicTeamQuery = function () {
return manager.executeQuery(entityQuery.from("Teams")).to$q();
};
EDIT 3 :
After some experimenting I managed to get this working with the following Breeze query :
this.basicTeamQuery = function () {
return manager.executeQuery(entityQuery.from("Teams").
select("TeamId, TeamName, FlagSmall, FlagLarge, BadgeSmall, BadgeLarge, TeamImage, " +
"Group.GroupName").expand("Group")).to$q();
};
Not sure if this is the correct way to do this, or even if it should work...isn't expand supposed to not work with Angular?
EDIT 4 :
Here is the final working query, no need for the select above :
this.basicTeamQuery = function () {
return manager.executeQuery(entityQuery.from("Teams").
expand("Group")).to$q();
};

I just tried it and it worked for me without any issue.
I see a typo in the snippet you copied in the question. Name of your navigation property defined in the Item class is Group, but you passed "Groups" to the Include function. Can you try it by fixing the typo and update if you still face the issue?
UPDATE:
It seems you cannot get the navigation property without using expand. Because, even the OData URL without expand doesn't send values of navigation properties despite of using Include in the LINQ query.

Try adding:
[ForeignKey("GroupId")]
[InverseProperty("Teams")]
public Group Group { get; set; }
EDIT:
After checking once again, I noticed that relationship is different than what I thought at first glance. Since one Group has MANY Teams, try query the other way:
[Queryable]
public IQueryable<Group> GetGroupsWithTeams()
{
return db.Groups.Include("Teams"); //get navigation property
}
That should return everything properly.

Related

Cannot Move Divs in Blazor

I have a Blazor Server App with the following DIV tags
<div class=mainScreen id="outerBox" style="width:#(TotalWidth)px;height:#(TotalHeight)px;">
foreach(Device thisDevice in MyDevices)
{
<div class=column id="#MainDiv" style="width:#(thisDevice.Width)px;height:#(thisDevice.Height)px;left:#thisDevice.XCoordinate;top:#thisDevice.YCoordinate">
Main Content Here...
</div>
}
</div>
I attempted to set the Height, Width, and X/Y coordinates using the code samples from this page - https://blazor.tips/blazor-how-to-ready-window-dimensions/ but that never worked and simply threw an uncaught exception no matter where I placed Try... blocks.
I then moved to a more straightforward JS call:
await Task.Run(async () =>
{
//Commenting out the OnInitializeAsync makes no difference but needs to be commented out when embedded
//On the main component
await this.OnInitializedAsync();
string data = await JSRuntime.InvokeAsync<string>("getMyWindow", new object[] { });
JObject offsets = (JObject)JsonConvert.DeserializeObject(data);
TotalHeight = offsets.Value<int>("height");
TotalHeight = offsets.Value<int>("width");
}
//In my JS file, the function looks as follows:
function getMyWindow() {
var obj = {};
obj.width = window.width;
obj.height = window.height;
return JSON.stringify(obj);
}
If I make this call directly in the code, nothing ever happens - even with the OnInitializeAsync commented out.
var result = SetDimensions().Result;
If I place this method in the OnAfterRendor method:
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
if (!SetTheDivs)
SetTheDivs = SetDimensions().Result;
StateHasChanged();
}
}
protected override void OnInitialized()
{
base.OnInitialized();
this.OnAfterRender(true);
}
everything hangs until I kill the project. There are never any errors but the code never runs when I place breakpoints on the height or width statements.
I even added in the Async version to no avail:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await SetDimensions();
StateHasChanged();
}
}
protected override async Task OnInitializedAsync()
{
await this.OnAfterRenderAsync(true);
}
Same result as everything hangs. I am at a complete loss as to how to proceed and I really could use some help!
As a point of clarity, it is the call to the JS that results in the hang:
string data = await JSRuntime.InvokeAsync<string>("getMyWindow", new object[] { });
I added in some alerts but they never run:
function getMyWindow() {
var obj = {};
alert("hi");
obj.width = screen.width;
obj.height = screen.height;
alert("ho");
return JSON.stringify(obj);
}
Thank you for your time!
BTW - I did change the double await to string data = JSRuntime.InvokeAsync<string>("getMyWindow", new object[] { }).Result;
UPDATE: I moved the JS call outside of the await altogether and I got the error:
InvalidOperationException: JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendered. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method.
In this case, I am literally calling the method from the OnAfterRenderAsync method:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnInitializedAsync();
if (firstRender)
{
await SetDimensions();
StateHasChanged();
}
}
Not sure what you want... Copy the code below and run it, and tell us if that is what you were trying to get.
Index.razor
#page "/"
<div class=mainScreen id="outerBox" style="width:#($"{TotalWidth}px");height:#($"{TotalHeight}px"); background-color: green; top:60px; position:absolute">
#foreach (Device device in devices)
{
<div class=column style="width:#($"{device.Width}px");height:#($"{device.Height}px");margin-left:#($"{device.Left}px");margin-top:#($"{device.Top}px"); background-color:aliceblue">
#device.Name: Main Content Here...
</div>
}
</div>
#code {
private int TotalWidth = 520;
private int TotalHeight = 530;
private IList<Device> devices = Enumerable.Range(1, 5).Select(i => new Device { Name = $"Name {i}", Width = 520, Height = 100, Left = 0, Top = 5 }).ToList();
public class Device
{
public string Name { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public int Left { get; set; }
public int Top { get; set; }
}
}
Note: The OnInitialized{Async} pair of methods are the life-cycle methods of the base class ComponentBase. They are automatically called by the Blazor framework when a Razor component is being created. They are executed only once. You may override them, and add your logics, but you SHOULD never call them manually from your code.
This:
protected override async Task OnInitializedAsync()
{
await this.OnAfterRenderAsync(true);
}
This is wrong and must never be done. You should not call OnAfterRender{Async}. It is the Blazor framework that should call OnAfterRender{Async}, not the developer. Could you try to comprehend what your code is doing...
Try to understand that though the Razor components are defined as C# classes, they are special cases of Classes, that require special handling by the framework...
Update
Ken Tola, the following code I believe does what you're looking for. It reads the width and height of the window object, pass it to the Index component, and relocate your dear divs. Note that before the app relocates the divs, I check the values of the width and height, and determine the dimensions of the divs. This is of course is done for demonstration purposes, and you can manipulate those values as you wish...
Index.razor
#page "/"
#implements IDisposable
#inject IJSRuntime JSRuntime
<div class=mainScreen id="outerBox" style="width:#($" {TotalWidth}px");height:#($"{TotalHeight}px"); background-color: green; top:60px; position:absolute">
#foreach (Device device in devices)
{
<div class=column style="width:#($" {device.Width}px");height:#($"{device.Height}px");margin-left:#($"{device.Left}px");margin-top:#($"{device.Top}px"); background-color:aliceblue">
#device.Name: Main Content Here...
</div>
}
</div>
#code
{
private DotNetObjectReference<BrowserService> objRef;
private BrowserService BSS;
private int TotalWidth;
private int TotalHeight;
private IList<Device> devices = Enumerable.Range(1, 5).Select(i => new Device { Name = $"Name {i}", Width = 520, Height = 100, Left = 0, Top = 5 }).ToList();
public class Device
{
public string Name { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public int Left { get; set; }
public int Top { get; set; }
}
protected override void OnInitialized()
{
BSS = new BrowserService();
objRef = DotNetObjectReference.Create(BSS);
BSS.Notify += OnNotify;
}
public void Dispose()
{
BSS.Notify -= OnNotify;
objRef?.Dispose();
}
public async Task OnNotify()
{
// Note that the notifier only notify your component
// that data is ready, and that the dimensions are read
// from a property. You can instead define event handler
// that pass the data in the form of EventArgs...
TotalWidth = BSS.Dimension.Width >= 877 ? 520 : 550;
TotalHeight = BSS.Dimension.Height >= 550 ? 800 : 1200;
await InvokeAsync(() => StateHasChanged());
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// This code is excuted only once, in order to initialize
// the JavaScript objects
if (firstRender)
{
await JSRuntime.InvokeAsync<object>
("myJsFunctions.getDimensions", objRef);
}
}
}
BrowserService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.JSInterop;
public class BrowserService
{
public event Func<Task> Notify;
#nullable enable
public Dimension? Dimension { get; set; }
#nullable disable
[JSInvokableAttribute("GetDimensions")]
public async Task GetDimensions(string dimension)
{
JsonSerializerOptions options = new(JsonSerializerDefaults.Web)
{
WriteIndented = true
};
var _dimension = System.Text.Json.JsonSerializer.Deserialize(dimension, typeof(Dimension), options);
Dimension = (Dimension)_dimension;
if (Notify != null)
{
await Notify?.Invoke();
}
}
}
public class Dimension
{
public int Width { get; set; }
public int Height { get; set; }
}
}
Startup.ConfigureServices
services.AddScoped<BrowserService>();
_Host.cshtml
<script src="_framework/blazor.server.js"></script>
<script type="text/javascript">
window.myJsFunctions = {
getDimensions: function (dotnetHelper) {
var dimension = {
width: window.innerWidth,
height: window.innerHeight
};
var json = JSON.stringify(dimension);
return dotnetHelper.invokeMethodAsync('GetDimensions', json);
}
};
</script>
Note: Consider handling the relocation of the div elements when the window is resized. It should be responsive, right ? Not sure that in your case you can employ media query. Any how, as you can see, I have designed the code in such a way that it takes into account that your div elements may need to be relocate again and again, thus it constantly (when resizing) notifies your Index component of the changing dimensions. I guess this merits a new question.....

Is there a way to pass multiple (and different) parameters to an Apex Controller class from JS in Lightning Web Components (LWC)?

I'm currently stuck at a problem and was hoping someone here could help me. I also certainly hope this is the right place to ask it.
I'm trying to create a custom Invoice record with its corresponding Invoice Line records upon firing an event. I already have some logic in place to gather ID of selected rows in the JS.
I've gone so far as to be able to create the Invoice record (using LDS) and the Invoice Line records (using Apex), but can't seem to pass the Invoice ID for the Invoice Line records. I know I'm able to create the records because it works when I tested this with a hardcoded Invoice ID.
Would it be possible to pass multiple parameters of List and String to an Apex method in LWC?
I would appreciate any help. Thanks in advance!
JS
selectedRowsEvent(event) {
...some codes here...
this.selectedRecords = Array.from(conIds);
}
handleSave() {
**invId;**
...some codes here...
createRecord(recordInput)
.then(invoice => {
**this.invId = invoice.Id;**
**createInvLines({ lstConIds : this.selectedRecords, invoiceId : this.invId})**
}).catch(error => {
...some codes here...
});
}
Controller
#AuraEnabled
public static void createInvLines(list<Id> lstConIds, string invoiceId){
if(lstConIds.size() > 0){
List<OpportunityLine__c> oppLst = new List<OpportunityLine__c>([SELECT Id, Description__c FROM OpportunityLine__c WHERE Id = :lstConIds]);
try {
List<InvoiceLine__c> lstInvLinesToInsert = new List<InvoiceLine__c>();
for(OpportunityLine__c idCon : oppLst) {
lstInvLinesToInsert.add(new InvoiceLine__c(**InvoiceId__c = invoiceId**, Description__c = idCon.Description__c));
}
if(!lstInvLinesToInsert.isEmpty()) {
insert lstInvLinesToInsert;
}
}
catch(Exception ex) {
throw new AuraHandledException(ex.getMessage());
}
}
}
Yes, you can pass complex parameters to methods marked as #AuraEnabled. On client side it'll be a JSON object with right field names, like you already have { lstConIds : this.selectedRecords, invoiceId : this.invId}. On Apex side it can be a function with multiple arguments or just 1 argument (some helper wrapper class, again with right field names). Salesforce will "unpack" that JSON for you and put into right fields before your code is called.
Your preference which would be cleaner. I tend to use wrappers. If you have a reusable service-like function and you want to add some optional parameters later - you'd simply put new field in wrapper class and job done. Might be not as easy to add a new parameter to function used in other apex code, bit messier.
(in your scenario I'd definitely try to create invoice and line items as 1 call so if anything fails - the normal transaction rollback will help you. if one of items fails - you don't want to be left with just invoice header, right?)
Have you seen https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex ? it's a wall of text but it mentions interesting example, search for "apexImperativeMethodWithParams" in there.
Look at JS file here: https://github.com/trailheadapps/lwc-recipes/tree/master/force-app/main/default/lwc/apexImperativeMethodWithComplexParams
And see how it calls
ApexTypesController {
#AuraEnabled(cacheable=true)
public static String checkApexTypes(CustomWrapper wrapper) {
...
Where CustomWrapper is
public with sharing class CustomWrapper {
class InnerWrapper {
#AuraEnabled
public Integer someInnerInteger { get; set; }
#AuraEnabled
public String someInnerString { get; set; }
}
#AuraEnabled
public Integer someInteger { get; set; }
#AuraEnabled
public String someString { get; set; }
#AuraEnabled
public List<InnerWrapper> someList { get; set; }
}
The issue is that the inserts are asynchronous and you are firing them synchronously. So, that means you are trying to insert the lines before the parent record has completed.
// CREATE THE INVOICE RECORD
createRecord(recordInput)
.then(invoice => {
**this.invId = invoice.Id;**
// Call the next function here
// CREATE THE INVOICE LINE RECORDS
**createInvLines({ lstConIds : this.selectedRecords, invoiceId : this.invId})**
.then(result => {
...some codes here...
})
.catch(error => {
...some codes here...
});
);
}

Toast notifications are not working on a JavaScript call

I'm developing an App with Xamarin.Android and I want to show a Toast notification while I'm exporting a report from JavaScript. My app calls the report and it's successfully generated. However, the Toast notification is never displayed. I discovered that only when I set a break point in that specific line it's shown in Visual Studio 2017.
This is part of my C# class for handling JS.
class CallJSInterface : Java.Lang.Object
{
private class Timetable
{
public string member { get; set; }
public string role { get; set; }
public string time { get; set; }
public string lastColor { get; set; }
}
private Context context;
public CallJSInterface(Context context)
{
this.context = context;
}
[Export]
[JavascriptInterface]
public void ExportToExcel(string results)
{
Toast.MakeText(context, context.GetString(Resource.String.LblExportMsg), ToastLength.Short).Show();
var timetable = JsonConvert.DeserializeObject<List<Timetable>>(results);
//Excel conversion
}
}
This is the value for the LblExportMsg in the Strings.xml:
<string name="LblExportMsg">Exporting your Agenda to Excel.</string>
Also, this is an example of I call the function in JS:
$("#linkDownload").click(function (e) {
e.preventDefault();
CSharp.ExportToExcel('[{"member":"Luis","role":"Timer","time":"00:15:15","lastColor":"red"},{"member":"Luis","role":"Timer 1","time":"00:15:00","lastColor":"green"},{"member":"Luis","role":"Timer 2","time":"00:15:17","lastColor":"red"},{"member":"Luis","role":"Timer 3","time":"00:07:15","lastColor":"green"},{"member":"Luis","role":"Timer 4","time":"00:23:15","lastColor":"red"},{"member":"Luis","role":"Timer 5","time":"00:15:15","lastColor":"green"},{"member":"Luis","role":"Timer 6","time":"01:15:15","lastColor":"yellow"},{"member":"Luis","role":"Timer 7","time":"00:18:15","lastColor":"green"},{"member":"Luis","role":"Timer 8","time":"00:15:22","lastColor":"green"}]');
});
Additionally, the HTML button:
<button type="button" id="linkDownload">Export</button>
Finally, this is how I add the JS interface to the WebView from the main activity:
webView.AddJavascriptInterface(new CallJSInterface(this), "CSharp");
Does anyone know what I am doing wrong? Is it something related to the context? How can I check it? Thanks for your help.
PS:
The minimum SDK is 21 and targets the SDK 27.
I'm using JSON.NET for deserializing.
I was able to fix it, I added a timeout before exporting the report and also, split in two the process one for displaying the Toast and another for the report.
$("#linkDownload").click(function (e) {
CSharp.Alert(currentTranslation.lblExportMsg);
setTimeout(function () {
CSharp.ExportToExcel(JSON.stringify(results));
}, 250);
});

Breeze when adding item many to many I need refresh page to add new item

Please skip this and read edit :)
I have entity which serves as many to many mapping for two other entities:
public class ExerciseAndCategory
{
#region Navigational properties
public int CategoryId { get; set; }
public virtual ExerciseCategory ExerciseCategory { get; set; }
public int ExerciseId { get; set; }
public virtual Exercise Exercise { get; set; }
#endregion
}
Here is FluentApi for it:
modelBuilder.Entity<ExerciseAndCategory>().HasKey(e => new {e.ExerciseId, e.CategoryId});
modelBuilder.Entity<ExerciseAndCategory>()
.HasRequired(e => e.Exercise)
.WithMany()
.HasForeignKey(e => e.ExerciseId)
.WillCascadeOnDelete(true);
modelBuilder.Entity<ExerciseAndCategory>()
.HasRequired(e => e.ExerciseCategory)
.WithMany()
.HasForeignKey(e => e.CategoryId)
.WillCascadeOnDelete(true);
And in database that looks like this:
To get and save data I'm using BreezeApi Controller, and I'm adding data as it is showed in breeze samples:
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _contextProvider.SaveChanges(saveBundle);
}
And In service (using Breeze) I send data to api like this:
addExerciseAndCategories: function (data, initialValues) {
var addedExercise = manager.createEntity("Exercise", initialValues);
_.forEach(data, function (item) {
var entity = manager.createEntity("ExerciseAndCategory", { ExerciseId: addedExercise._backingStore.ExerciseId, CategoryId: item.CategoryId });
items.push(entity);
});
saveChanges().fail(addFailed);
function addFailed() {
removeItem(items, item);
}
},
With this I can add item to database, but if I want to add another one without refreshing,
I get exception at this part of code:
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _contextProvider.SaveChanges(saveBundle);
}
Saying
DBUpdateException was unhandeled by user code
An error occurred while updating the entries. See the inner exception for details.
And in Javascript console:
"Error: Error: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.ExerciseAndCategories_dbo.Exercises_ExerciseId". The conflict occurred in database "aspnet-Web.UserInterface.Web-20130806182934", table "dbo.Exercises", column 'ExerciseId'.
The statement has been terminated."
But if I refresh after adding, everything works fine. (i.e. I can add another item)
EDIT
I've found very bad workaround for a problem. And problem is that, ExerciseId is -1 before calling saveChanges(). I've decided to separate adding exercise and categories in two different functions. And my code looked like this:
addExercise: function (initialValues) {
exerciseToAdd = manager.createEntity("Exercise", initialValues);
saveChanges().fail(addFailed);
function addFailed() {
removeItem(items, item);
}
},
addExerciseAndCategories: function(data) {
newItems = [];
logger.log("id is", exerciseToAdd.ExerciseId);
_.forEach(data, function(item) {
var entity = manager.createEntity("ExerciseAndCategory", { ExerciseId: exerciseToAdd.ExerciseId, CategoryId: item.CategoryId });
items.push(entity);
newItems.push(entity);
});
saveChanges().fail(addFailed);
var itemsToAdd = addCategoriesToExercise(newItems);
_.forEach(itemsToAdd, function(item) {
exerciseAndCategories.push(item);
});
}
And this didn't work, same error. So in console I've noticed that ExerciseId is still -1, and then I decided to use angular's $timeout and wait for a few seconds and then log ExerciseId, after that ExerciseId was int greater than -1, i.e. it worked fine, so I've changed code to this (and everything works as it should):
addExerciseAndCategories: function(data) {
newItems = [];
$timeout(function() {
logger.log("id je", exerciseToAdd.ExerciseId);
_.forEach(data, function (item) {
var entity = manager.createEntity("ExerciseAndCategory", { ExerciseId: exerciseToAdd.ExerciseId, CategoryId: item.CategoryId });
items.push(entity);
newItems.push(entity);
});
saveChanges().fail(addFailed);
var itemsToAdd = addCategoriesToExercise(newItems);
_.forEach(itemsToAdd, function(item) {
exerciseAndCategories.push(item);
});
},5000);
function addFailed() {
removeItem(items, item);
}
},
Finally, as I know this is very bad solution, my question is, how can I get around this ? Is there any way for me to know that Exercise was inserted into database and that ExerciseId isn't -1 anymore ? Or can I generate ExerciseId (which is int) on client-side ?
Breeze does not yet support many to many relationship for Entity Framework, although it is on our roadmap. Please vote for it on the Breeze User Voice here. As a workaround you can use two one-many relations with your mapping table exposed as an entity in the middle.
For example: if you have a conceptual many to many relationship like this:
Employee (m) <--> (m) Territory
Properties: Employee.Territories (m)
Territory.Employees (m)
You can instead construct this by adding a new EntityType (EmpTerritory) in the middle:
Employee (1) <--> (m) EmpTerritory (m) <--> Territory (1)
Properties: Employee.EmployeeTerritories (m),
Territory.EmployeeTerritories (m),
EmployeeTerritory.Employee (1),
EmployeeTerritory.Territory (1)
You can still navigate from an Employee to its Territories and vice versa, but you need to go thru the intermediate Entity first.

Save data to ViewState

I can tried save some data to ViewState, but i get this Error:
Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerServerErrorException: Error serializing value 'HeRMeSSAAS.BussinesProcess.BussinesServices.CandidateService' of type 'HeRMeSSAAS.BussinesProcess.BussinesServices.CandidateService.'
Code:
private IActionService ActionService
{
get
{
return ViewState["ActionService"] as IActionService;
}
set
{
ViewState["ActionService"] = value;
}
}
private void InitializeField(IActionService service)
{
ActionService = service;
}
How i can store value to ViewState?
s your HeRMeSSAAS.BussinesProcess.BussinesServices.CandidateService decorated with the Serializable attribute?
eg:
[Serializable]
public class CandidateService
{
}
if this is not a very simple class I would also recommend storing it in the Session rather than the ViewState as it will take longer for the page to download and render
you need the [Serializable] Attribute on top of your business object.

Categories

Resources