I am preparing to using Timeglider to create a timeline. One requirement is the data has to be in JSON format. One requirement for me is it needs to be client side as I do not have access to the servers or central admin.
When I try to do http://webname/_vti_bin/ListData.svc/listname I get an error for access permissions however when I issue it http://webname/subsite/_vti_bin/ListData.svc/listname I have no problem pulling data.
My situation is the list is on the TLD. I tried to follow this post How to retrieve a json object from a sharepoint list but it relates to SP 2007.
To implement pure JSON support in SharePoint 2007, 2010 and so on have a look at this project, http://camelotjson.codeplex.com/. It requires the commercial product Camelot .NET Connector to be installed on the server.
If you don't like to go commercial you can resort to the sp.js library, here is a small example I wrote, enjoy!
// Object to handle some list magic
var ListMagic = function () {
/* Private variables */
var that = this;
var clientContext = SP.ClientContext.get_current();
var web = clientContext.get_web();
var lists = web.get_lists();
/**
* Method to iterate all lists
*/
that.getLists = function () {
clientContext.load(lists);
clientContext.executeQueryAsync(execute, getFailed);
function execute() {
var listEnumerator = lists.getEnumerator();
while (listEnumerator.moveNext()) {
var l = listEnumerator.get_current();
// TODO! Replace console.log with actual routine
console.log(l.get_title());
}
}
function getFailed() {
// TODO! Implement fail management
console.log('Failed.');
}
};
/**
* Method to iterate all fields of a list
*/
that.getFields = function (listName) {
// Load list by listName, if not stated try to load the current list
var loadedList = typeof listName === 'undefined' ? lists.getById(SP.ListOperation.Selection.getSelectedList()) : that.lists.getByTitle(listName);
var fieldCollection = loadedList.get_fields();
clientContext.load(fieldCollection);
clientContext.executeQueryAsync(execute, getFailed);
function execute() {
var fields = fieldCollection.getEnumerator();
while (fields.moveNext()) {
var oField = fields.get_current();
// TODO! Replace console.log with actual routine
var listInfo = 'Field Title: ' + oField.get_title() + ', Field Name: ' + oField.get_internalName();
console.log(listInfo);
}
}
function getFailed() {
// TODO! Implement fail management
console.log('Failed.');
}
};
/**
* Method to get a specific listitem
*/
that.getListItem = function (itemId) {
var loadedList = lists.getById(SP.ListOperation.Selection.getSelectedList());
var spListItem = loadedList.getItemById(itemId);
clientContext.load(spListItem);
clientContext.executeQueryAsync(execute, getFailed);
function execute() {
// TODO! Replace console.log with actual routine
//spListItem.get_fieldValues()
console.log(spListItem.get_fieldValues()["Title"]);
}
function getFailed() {
// TODO! Implement fail management
console.log('Failed.');
}
};
/**
* Method to fake an init (optional)
*/
that.init = function () {
// Run any init functionality here
// I.e
that.getFields("Tasks");
};
return that;
};
// In case of no jquery use window.onload instead
$(document).ready(function () {
ExecuteOrDelayUntilScriptLoaded(function () {
var sp = new ListMagic();
sp.init();
}, 'sp.js');
});
Personally, I make HttpHandlers. I install them in the SharePoint isapi folder and the GAC and I can call them just like you might the owssvr.dll. http://servername/_vti_bin/myhttphandelr.dll
Pass it querystring variables or call it from jquery ajax. You can use the httpcontext and make a spcontext from it and have access to all sorts of information from the current location in SharePoint. Then you can javascriptserialize the objects and pass them as JSON. Looking for some code... Hang on... I can't put all the code but this should get you close. I use this to add a submenu to the context menu to allow a user to delete or rename a file if they uploaded it to a library and it is version 1.0 and to collect a file from a library and create a eml file with the selected file(s) as an attachment(s). We don't give our users delete privileges normally. Point being, you can now create a class with just the information you need from SharePoint and pass it as JSON. The only downfall I have with this, is iisreset is required if you make any changes to the dll.
I task schedule a iisreset every night at midnight anyway to keep it fresh and free from memory bloat. I come in the next day and my changes are there. The cool thing is, the spcontext has information about the current location in SharePoint from where it is called. So, http://servername/_vti_bin/myhttphandelr.dll vs http://servername/subsite/library/_vti_bin/myhttphandelr.dll
I might add. Don't try to serialize SharePoint objects. One they are huge, complex objects. Two, I don't think they are marked serializable. Just make you own class and populate it with the values you need from the SharePoint objects.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.ComTypes;
using System.Web;
using System.Web.Script.Serialization;
using ADODB;
using interop.cdosys;
using Microsoft.SharePoint;
namespace owssvr2
{
public class OWSsvr2 : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{
private string cmd;
ctx ctx = new ctx();
private string currentuser;
private SPContext SPcontext;
private HttpContext cntx;
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
SPcontext = SPContext.GetContext(context); <-- Gets spcontext from the httpcontext
cntx = context;
ctx = GetData(context.Request); <-- I parse some information from the request to use in my app
cmd = ctx.Cmd;
ctx.User = context.User.Identity.Name;
currentuser = context.User.Identity.Name;
switch (cmd)
{
case "Delete":
Delete();
context.Response.Redirect(ctx.NextUsing);
break;
case "HasRights":
HasRights();
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
string serEmployee = javaScriptSerializer.Serialize(ctx);
context.Response.Write(serEmployee);
context.Response.ContentType = "application/json; charset=utf-8";
break;
case "Rename":
Rename(context);
//context.Response.Redirect(context.Request["NextUsing"]);
break;
case "SendSingleFile":
try
{
context.Response.Clear();
context.Response.ClearHeaders();
context.Response.BufferOutput = true;
ADODB.Stream stream = SendSingleFile(context.Request["URL"]);
stream.Type = StreamTypeEnum.adTypeBinary;
stream.Position = 0;
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("content-disposition", "attachment;filename=Email.eml");
IStream iStream = (IStream)stream;
byte[] byteArray = new byte[stream.Size];
IntPtr ptrCharsRead = IntPtr.Zero;
iStream.Read(byteArray, stream.Size, ptrCharsRead);
context.Response.BinaryWrite(byteArray);
context.Response.End();
}
catch(Exception ex) {context.Response.Write(ex.Message.ToString()); }
break;
case "SendMultiFile":
try
{
//SendMultiFile(context.Request["IDs"]);
context.Response.Clear();
context.Response.ClearHeaders();
context.Response.BufferOutput = true;
ADODB.Stream stream = SendMultiFile(context.Request["IDs"]);
stream.Type = StreamTypeEnum.adTypeBinary;
stream.Position = 0;
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("content-disposition", "attachment;filename=Email.eml");
IStream iStream = (IStream)stream;
byte[] byteArray = new byte[stream.Size];
IntPtr ptrCharsRead = IntPtr.Zero;
iStream.Read(byteArray, stream.Size, ptrCharsRead);
context.Response.BinaryWrite(byteArray);
context.Response.End();
}
catch(Exception ex) {context.Response.Write("There was an error getting the files. </br>" + ex.Message.ToString()); }
break;
case "FileInfo":
JavaScriptSerializer javaScriptSerializer1 = new JavaScriptSerializer();
string serEmployee1 = javaScriptSerializer1.Serialize(FileInfo(context));
context.Response.Write(serEmployee1);
context.Response.ContentType = "application/json; charset=utf-8";
break;
case "UsersInGroups":
UsersInGroups ug = new UsersInGroups(context, context.Request["job"],context.Request["groups"]);
break;
}
}
Related
I've implemented an IMvxNavigationFacade for deep linking in my MvvmCross 5.6.x sample app. I've added logic in BuildViewModelRequest() to construct a MvxViewModelRequest with parameters passed in as MvxBundle.
if (url.StartsWith("http://www.rseg.net/rewards/"))
{
var parametersBundle = new MvxBundle();
var id = url.Substring(url.LastIndexOf('/') + 1);
parametersBundle.Data.Add("id", id);
return Task.FromResult(
new MvxViewModelRequest(typeof(RewardDetailViewModel),
parametersBundle, null));
}
However, this approach causes the old style Init() method to be called in the target ViewModel rather than the new typesafe Prepare() method.
public class RewardDetailViewModel :
MvxViewModel<RewardDetailViewModel.Parameteres>
{
...
public new void Init(string id)
{
if (!string.IsNullOrWhiteSpace(id))
{
if (int.TryParse(id, out _rewardId))
RaiseAllPropertiesChanged();
}
}
public override void Prepare(Parameteres parameter)
{
if (parameter != null)
{
_rewardId = parameter.RewardId;
RaiseAllPropertiesChanged();
}
}
}
Is there a way to construct a MvxViewModelRequest so that you pass in an instance of the parameter class for the target ViewModel causing the Prepare() method to be called?
The entire solution can be viewed on GitHub https://github.com/rsegtx/So.MvvmNav2
Thanks in advance!
After doing some research I found at lease one way to accomplish this.
Create a ViewModelInstanceRequest rather than a ViewModelRequest so that you can call ViewModelLoader.LoadViewModel passing in a parameters object; the ViewModelRequest only allows parameters to be passed using a MvxBundle. Make the following change to BuildViewModelRequest() on the NavigationFacade:
var request = new
MvxViewModelInstanceRequest(typeof(RewardDetailViewModel));
var parameters = new RewardDetailViewModel.Parameteres();
.... parse parameters and fill in parameters object
request.ViewModelInstance = ViewModelLoader.LoadViewModel(
request, parameters, null);
return Task.FromResult((MvxViewModelRequest)request);
Create your own IMvxNavigationService and add logic to inspect the object returned from the NavigationFacde and if it is a ViewModelInstanceRequest then use it as is rather than one previously creating.
var facadeRequest = await facade.BuildViewModelRequest(path,
paramDict).ConfigureAwait(false);
...
if (facadeRequest is MvxViewModelInstanceRequest)
request = facadeRequest as MvxViewModelInstanceRequest;
else
{
facadeRequest.ViewModelType = facadeRequest.ViewModelType;
if (facadeRequest.ParameterValues != null)
{
request.ParameterValues = facadeRequest.ParameterValues;
}
request.ViewModelInstance = ViewModelLoader.LoadViewModel(
request, null);
}
I've updated the original example on GitHub https://github.com/rsegtx/So.MvvmNav2.
I'm trying to read an external json to display data on screen. What am I doing worng here?
public void QuarterlyReport(object sender, EventArgs e)
{
JObject qData1 = JObject.Parse(System.IO.File.ReadAllText(#"~/json/quarterlyData.json"));
// read JSON directly from a file
using (StreamReader file = System.IO.File.OpenText(#"~/json/quarterlyData.json"))
using (JsonTextReader reader = new JsonTextReader(file))
{
JObject Qdata2 = (JObject) JToken.ReadFrom(reader);
}
string Qdata = Newtonsoft.Json.JsonConvert.SerializeObject(qData1);
}
public async Task<FileStreamResult> Index()
{
var _reportingService = new ReportingService("https://mysite.jsreportonline.net", "myemail#gmail.com", "password");
var report = await _reportingService.RenderAsync("VyxOYwH7Ze", new { Qdata });
//add the stream to be used by browser
MemoryStream ms = new MemoryStream();
//copy whatever JS is sending to us
report.Content.CopyTo(ms);
//start at content point
ms.Position = 0;
//send this to browser
return File(ms, report.ContentType.MediaType);
}
I can't seem to get the vaule into the variable Qdata. What is it that I am doing wrong in the method?
The line where you declare Qdata:
string Qdata = Newtonsoft.Json.JsonConvert.SerializeObject(qData1);
is not in the same scope as this line:
var report = await _reportingService.RenderAsync("VyxOYwH7Ze", new { Qdata });
Yes, the problem was that
JObject qData1 = JObject.Parse(System.IO.File.ReadAllText(#"~/json/quarterlyData.json"));
And
string Qdata = Newtonsoft.Json.JsonConvert.SerializeObject(qData1);
Needed to be in the same scope as
var report = await _reportingService.RenderAsync("VyxOYwH7Ze", new { Qdata });
I am using C# and the Exchange Web Services API and have been unable to find a way to retrieve a contact using the extended property named Account. We have used this field to hold an integer number that is meaningful to an in-house developed system. Under WebDAV, we knew how to retrieve the Contact but need some help (hopefully a short example or code snippet) to demonstrate how to do this.
I have used extended property with appointments, so maybe they work on the same concept as the contacts.
The Idea is to put a Guid for appointments as their native IDs are not constant.
private static readonly PropertyDefinitionBase AppointementIdPropertyDefinition = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "AppointmentID", MapiPropertyType.String);
public static PropertySet PropertySet = new PropertySet(BasePropertySet.FirstClassProperties, AppointementIdPropertyDefinition);
//Setting the property for the appointment
public static void SetGuidForAppointement(Appointment appointment)
{
try
{
appointment.SetExtendedProperty((ExtendedPropertyDefinition)AppointementIdPropertyDefinition, Guid.NewGuid().ToString());
appointment.Update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToNone);
}
catch (Exception ex)
{
// logging the exception
}
}
//Getting the property for the appointment
public static string GetGuidForAppointement(Appointment appointment)
{
var result = "";
try
{
appointment.Load(PropertySet);
foreach (var extendedProperty in appointment.ExtendedProperties)
{
if (extendedProperty.PropertyDefinition.Name == "AppointmentID")
{
result = extendedProperty.Value.ToString();
}
}
}
catch (Exception ex)
{
// logging the exception
}
return result;
}
Not sure if you still need this... but I just solved something close myself:
My answer here should be in the ballpark of what you want. I'm using a boolean as well as Account here:
ExchangeService service = this.GetService(); // my method to build service
FolderId folderID = GetPublicFolderID(service, "My Address Book");
ContactsFolder folder = ContactsFolder.Bind(service, folderID);
int folderCount = folder.TotalCount;
var guid = DefaultExtendedPropertySet.PublicStrings;
var epdAccount = new ExtendedPropertyDefinition(0x3A00, MapiPropertyType.String);
var epdCID = new ExtendedPropertyDefinition(0x3A4A, MapiPropertyType.String);
var epdCBLN = new ExtendedPropertyDefinition(guid, "CustomBln", MapiPropertyType.Boolean);
var epdCDBL = new ExtendedPropertyDefinition(guid, "CustomDbl", MapiPropertyType.Double);
var view = new ItemView(folderCount);
view.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
view.PropertySet.Add(epdAccount);
view.PropertySet.Add(epdCID);
view.PropertySet.Add(epdCBLN);
view.PropertySet.Add(epdCDBL);
//var searchOrFilterCollection = new List<SearchFilter>();
//searchOrFilterCollection.Add(new SearchFilter.IsEqualTo(epdCBLN, true));
//searchOrFilterCollection.Add(new SearchFilter.IsEqualTo(epdAccount, "user"));
//var filter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, searchOrFilterCollection);
var filter = new SearchFilter.IsEqualTo(epdAccount, "user");
var contacts = service.FindItems(folderID, filter, view);
foreach (Contact contact in contacts)
{
string Account;
int CID;
bool CBLN;
double CDBL;
contact.GetLoadedPropertyDefinitions();
contact.TryGetProperty(epdAccuont, out Account);
contact.TryGetProperty(epdCID, out CID);
contact.TryGetProperty(epdCBLN, out CBLN);
contact.TryGetProperty(epdCDBL, out CDBL);
Console.WriteLine(String.Format("{0, -20} - {1} - {2} - {3} - {4}"
, contact.DisplayName
, contact.EmailAddresses[EmailAddressKey.EmailAddress1]
, Account
, CID
, CBLN
, CDBL
));
}
Got it working - Posted My solution below but will like to know if there is better way
Hello All
I am trying to create Domain Event for a newly created (after migration) domain object in my database.
for Objects without any internal child objects it worked fine by using Script Component. The problem is in how to get the child rows to add information to event object.
Ex. Customer-> Customer Locations.
I am creating Event in Script Component- as tranformation- (have reference to my Domain event module) and then creating sending serialized information about event as a column value. The input rows currently provide data for the parent object.
Please advise.
Regards,
The Mar
Edit 1
I would like to add that current I am doing processsing in
public override void Input0_ProcessInputRow(Input0Buffer Row)
I am looking for something like create a a data reader in this function
loop through data rows -> create child objecta nd add it to parent colelction
Still on google and PreExecute and ProcessInput Seems something to look at .
This is my solution. I am a total newbie in SSIS , so this may not be the best solution.
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
IDTSConnectionManager100 connectionManager;
SqlCommand cmd = null;
SqlConnection conn = null;
SqlDataReader reader = null;
public override void AcquireConnections(object Transaction)
{
try
{
connectionManager = this.Connections.ScriptConnectionManager;
conn = connectionManager.AcquireConnection(Transaction) as SqlConnection;
// Hard to debug failure- better off logging info to file
//using (StreamWriter outfile =
// new StreamWriter(#"f:\Migration.txt"))
//{
// outfile.Write(conn.ToString());
// outfile.Write(conn.State.ToString());
//}
}
catch (Exception ex)
{
//using (StreamWriter outfile =
// new StreamWriter(#"f:\Migration.txt"))
//{
// outfile.Write(" EEEEEEEEEEEEEEEEEEEE"+ ex.ToString());
//}
}
}
public override void PreExecute()
{
base.PreExecute();
cmd = new SqlCommand("SELECT [CustomerLocation fields] FROM customerlocationView where custid=#CustId", conn);
cmd.Parameters.Add("CustId", SqlDbType.UniqueIdentifier);
}
public override void PostExecute()
{
base.PostExecute();
/*
Add your code here for postprocessing or remove if not needed
You can set read/write variables here, for example:
Variables.MyIntVar = 100
*/
}
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
Collection<CustomerLocation> locations = new Collection<CustomerLocation>();
cmd.Parameters["CustId"].Value = Row.id;
// Any error always saw that reader reamians open on connection
if (reader != null)
{
if (!reader.IsClosed)
{
reader.Close();
}
}
reader = cmd.ExecuteReader();
if (reader != null)
{
while (reader.Read())
{
// Get Child Details
var customerLocation = new CustomerLocation(....,...,...,);
customerLocation.CustId = Row.id;
locations.Add(customerLocation);
}
}
var newCustomerCreated = new NewCustomerCreated(Row.id,,...,...,locations);
var serializedEvent = JsonConvert.SerializeObject(newCustomerCreated, Formatting.Indented,
new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
Row.SerializedEvent = serializedEvent;
Row.EventId = newCustomerCreated.EventId;
...
...
...
....
..
.
Row.Version = 1;
// using (StreamWriter outfile =
// new StreamWriter(#"f:\Migration.txt", true))
// {
// if (reader != null)
// {
// outfile.WriteLine(reader.HasRows);
//outfile.WriteLine(serializedEvent);
// }
// else
// {
// outfile.Write("reader is Null");
// }
//}
reader.Close();
}
public override void ReleaseConnections()
{
base.ReleaseConnections();
connectionManager.ReleaseConnection(conn);
}
}
One thing to note is that a different approach to create connection is to
get the connection string from connectionManager and use it to create OLEDB connection.
I am trying to implement the MVVM patter for my WP7 Silverlight app and I am running into a problem with the async JSON Rest call. I moved into my ViewModel class the following two methods that were on my WP7 app Page.
public void FetchGames()
{
ObservableCollection<Game> G = new ObservableCollection<Game>();
//REST call in here
var webClient = new WebClient();
Uri uri = new Uri("http://www.somewebsite.com/get/games/league/" + league);
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenReadCompletedGames);
webClient.OpenReadAsync(uri);
}
private void OpenReadCompletedGames(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;
ser = new DataContractJsonSerializer(typeof(ObservableCollection<Game>));
Games = ser.ReadObject(e.Result) as ObservableCollection<Game>;
this.IsDataLoaded = true;
}
Now the problem is that because it is an async call the following code does not work. The following code is on my app Page.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (NavigationContext.QueryString.TryGetValue("league", out league))
{
try
{
App.gViewModel.league = league;
App.gViewModel.FetchGames();
if(App.gViewModel.IsDataLoaded)
{
lbTeams.ItemsSource = App.gViewModel.Games;
}
}
catch ()
{
//error logging in here
}
}
}
Stepping thru the code shows that FetchGames is called then hits the next line ( if(App.gViewModel.IsDataLoaded)
) before the async call is finished. So IsDataLoaded is always false and I cant bind the listbox on the page.
Doing a lot of googleing I have some possible solutions but I am unable convert them to my particular problem. One is like this and it has to do with continuation passing style'. I couldn't get it to work tho and would greatly appreciate some help.
Thanks!
void DoSomethingAsync( Action<string> callback ) {
HttpWebRequest req; // TODO: build your request
req.BeginGetResponse( result => {
// This anonymous function is a closure and has access
// to the containing (or enclosing) function.
var response = req.EndGetResponse( result );
// Get the result string and call the callback
string resultString = null; // TODO: read from the stream
callback(resultString);
}, null );
}
This can be resolved by moving
lbTeams.ItemsSource = App.gViewModel.Games;
to the end of the OpenReadCompletedGames method. You'll need to use the Dispatcher to update the UI from here.
Dispatcher.BeginInvoke( () => { lbTeams.ItemsSource = App.gViewModel.Games; } );