Create field in SharePoint programmatically using CSOM (Not with XML) - sharepoint

Is it possible to create fields in SharePoint with CSOM, not using XML?
I've seen many examples using XML, but none with just setting properties for the field programmatically?
fields.Add(new **FieldCreationInformation** {
InternalName = "Test",
etc..
});

That's doable, in the following example is introduced a FieldCreationInformation class:
[XmlRoot("Field")]
public class FieldCreationInformation
{
[XmlAttribute("ID")]
public Guid Id { get; set; }
[XmlAttribute()]
public string DisplayName { get; set; }
[XmlAttribute("Name")]
public string InternalName { get; set; }
[XmlIgnore()]
public bool AddToDefaultView { get; set; }
//public IEnumerable<KeyValuePair<string, string>> AdditionalAttributes { get; set; }
[XmlAttribute("Type")]
public FieldType FieldType { get; set; }
[XmlAttribute()]
public string Group { get; set; }
[XmlAttribute()]
public bool Required { get; set; }
public string ToXml()
{
var serializer = new XmlSerializer(GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
var emptyNamepsaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, this, emptyNamepsaces);
return stream.ToString();
}
}
public FieldCreationInformation()
{
Id = Guid.NewGuid();
}
}
and then extension method for creating a new field:
public static class FieldCollectionExtensions
{
public static Field Add(this FieldCollection fields, FieldCreationInformation info)
{
var fieldSchema = info.ToXml();
return fields.AddFieldAsXml(fieldSchema, info.AddToDefaultView, AddFieldOptions.AddFieldToDefaultView);
}
}
Usage
var fieldInfo = new FieldCreationInformation();
fieldInfo.FieldType = FieldType.Geolocation;
fieldInfo.InternalName = "ContactsLocation";
fieldInfo.DisplayName = "Contacts Location";
ctx.Site.RootWeb.Fields.Add(fieldInfo);
ctx.ExecuteQuery();

When I add fields with CSOM/JSOM I use the method on the FieldCollection AddFieldAsXml. This requires you to build a string of xml with all of the properties for the desired field, but it works. I included an excerpt of the related cpde below:
Microsoft.SharePoint.Client.Web web = _context.Web;
FieldCollection fields = web.Fields;
_context.Load(fields);
_context.ExecuteQuery();
Field field = fields.FirstOrDefault(f => f.StaticName == _staticName);
if (field == null)
{
Field createdField = fields.AddFieldAsXml(xml, false, AddFieldOptions.AddToNoContentType);
_context.Load(createdField);
_context.ExecuteQuery();
}
Similar code is used if you would like to add a field directly to an existing list.

Related

How can i execute filter from our JSON filter JSON?

I have a vue3 datagrid and I want to fill the data in this grid with filter by API. At the same time, I want to send the filter fields in the grid to the API as JSON and execute them according to this filter on the API side. How can I do this with AutoQuery?
[Route("/GetConnectors", "POST")]
public class GetConnectors : QueryDb<Connector>
{
public string Id { get; set; }
public string PageParameterJson { get; set; }
}
public class Connector
{
[PrimaryKey]
[AutoIncrement]
public long PKey { get; set; }
public string Id { get; set; }
public string Name { get; set; }
}
public class PageParameters
{
public string Field { get; set; }
public string Operand { get; set; }
public string Value { get; set; }
public string Type { get; set; }
}
It's an example PageParameter JSON;
[
{
"Field":"Name",
"Operand":"cn"//Contains
"Value":"test",
"Type":"string"
},
{
"Field":"Id",
"Operand":"eq"//Equal
"Value":"2",
"Type":"string"
}
]
public async Task<object> Any(GetConnectors query)
{
using var db = AutoQuery.GetDb(query, base.Request);
var filters = query.PageParameters.FromJson<List<PageParameter>>();
//How can I execute query with for CreateQuery?
var q = AutoQuery.CreateQuery(query, Request, db);
var sql = q.PointToSqlString();
return await AutoQuery.ExecuteAsync(query, q, base.Request, dbConnection);
}
Best Regards
i can't execute dynamic filters from server-side datagrid
The AutoQuery.CreateQuery returns OrmLite's Typed SqlExpression which has a number of filtering options inc .Where(), .And(), .Or(), etc.
So you should be able to populate it with something like:
foreach (var filter in filters)
{
var type = filter.Type switch
{
"string" => typeof(string),
_ => throw new NotSupportedException($"Type {filterType}")
};
var value = filter.Value.ConvertTo(type);
if (filter.Operand == "eq")
{
q.And(filter.Field + " = {0}", value)
}
else if (filter.Operand == "cn")
{
q.And(filter.Field + " LIKE {0}", $"%{value}%")
}
else throw new NotSupportedException(filter.Operand);
}
Note: I've rewritten API to be async as you should never block on async methods.

Xml Parsing in C#

http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.atom on this site, I wrote the following code to retrieve the data.
protected void Button1_Click(object sender, EventArgs e)
{
string adresal = "http://" + txtAd.Text;
WebResponse GelenCevap;
WebRequest adresistegi = HttpWebRequest.Create(adresal);
GelenCevap = adresistegi.GetResponse();
StreamReader CevapOku = new StreamReader(GelenCevap.GetResponseStream());
string KaynakKodlar = CevapOku.ReadToEnd();
XmlDocument xmlDoc = new XmlDocument(); // Create an XML document object
xmlDoc.Load("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.atom"); // Load the XML document from the specified file
XmlNodeList depremler = xmlDoc.GetElementsByTagName("entry");
foreach (XmlNode node in depremler)
{
var a = node.ChildNodes;
foreach (XmlElement x in a)
{
ListBox1.Items.Add(x.InnerText);
}
}
}
In this way I get all the data in the ListBox.But I need to assign them to variable data line by line.How can I do? I would appreciate if you can help.
Also i need id,title, updated, georss:point,georss:elev variables.
First add an Enrty and Category class:
public class Entry
{
public string Id { get; set; }
public string Title { get; set; }
public string Updated { get; set; }
public string Summary { get; set; }
public string GPoint { get; set; }
public string GElev { get; set; }
public List<string> Categories { get; set; }
}
public class Category
{
public string Label { get; set; }
public string Term { get; set; }
}
Then use LINQ to XML
XDocument xDoc = XDocument.Load("path");
List<Entry> entries = (from x in xDoc.Descendants("entry")
select new Entry()
{
Id = (string) x.Element("id"),
Title = (string)x.Element("title"),
Updated = (string)x.Element("updated"),
Summary = (string)x.Element("summary"),
GPoint = (string)x.Element("georss:point"),
GElev = (string)x.Element("georss:elev"),
Categories = (from c in x.Elements("category")
select new Category
{
Label = (string)c.Attribute("label"),
Term = (string)c.Attribute("term")
}).ToList();
}).ToList();

Get the All Infromation of SharePoint Server using Client Object Model

I want to Create a Windows Application that
Display :
all Web Application,
Sites Collection of Each web Applications,
Sites of Each Site Collection,
Sub-Sites of Each Sites,
All lists-Libraries of Each Site and Sub-Sites in Tree-view
here i don't want to Give any Static URL, on Application Start up That All Information Filled Automatically in Tree-view if SharePoint is Installed on that Computer.
Is this Possible ? if yes then how ?
.Net Managed Client Object Model: Fetch All Webs, Libraries, Items
In SharePoint 2010, we have 3 client object model.
.Net Managed Client Object Model
Silverlight
ECMA Script / JavaScript
Today, I am presenting .NET Managed Client Object Model to retrieve all webs, libraries, items from SharePoint.
Prerequisites References for your desktop application:
1. Microsoft.SharePoint.Client.dll
2. Microsoft.SharePoint.Client.Runtime.dll
My Custom Classes to feel like we are working on SharePoint Server Object model:
public class SPWeb
{
public string WebGUID { get; set; }
public string Title { get; set; }
public string ServerRelativeUrl { get; set; }
public string ParentType { get; set; }
public SPBase Parent { get; set; }
}
public class SPList
{
public string ListGUID { get; set; }
public string Title { get; set; }
public string ParentWebUrl { get; set; }
public string RootFolderServerRelativeUrl { get; set; }
}
public class SPFolder
{
public string ID { get; set; }
public string UniqueID { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string ParentWebUrl { get; set; }
public string ListName { get; set; }
public string ServerRelativeUrl { get; set; }
public string ParentFolderServerRelativeUrl { get; set; }
}
public class SPListItem
{
public string ID { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string ServerRelativeUrl { get; set; }
public string Modified { get; set; }
public string ModifiedBy { get; set; }
public string CreatedBy { get; set; }
public string Size { get; set; }
public string Created { get; set; }
public string UniqueId { get; set; }
public string ListName { get; set; }
}
Methods which is used to fetch Webs / libraries / Items:
public List<SPWeb> GetAllWebs(string webURL)
{
var webColl = new List<SPWeb>();
try
{
var currentWeb = _ctx.Site.OpenWeb(webURL);
var allWebs = currentWeb.Webs;
var webCollection = _ctx.LoadQuery(allWebs.Include(web => web.Title,
web => web.Id, web => web.ServerRelativeUrl));
_ctx.ExecuteQuery();
webColl.AddRange(webCollection.Select(web => new SPWeb
{
Title = web.Title,
WebGUID = web.Id.ToString(),
ServerRelativeUrl = web.ServerRelativeUrl
}));
}
catch (Exception ex)
{
// error log
}
return webColl;
}
public List<SPList> GetAllLibraries(string webURL)
{
var listColl = new List<SPList>();
try
{
var currentWeb = _ctx.Site.OpenWeb(webURL);
var query = from list in currentWeb.Lists
where list.BaseType == BaseType.DocumentLibrary
select list;
var AllLists = currentWeb.Lists;
var listCollection = _ctx.LoadQuery(query.Include(myList => myList.Title,
myList => myList.Id,
myList => myList.RootFolder.ServerRelativeUrl,
myList => myList.ParentWebUrl,
myList => myList.Hidden,
myList => myList.IsApplicationList));
_ctx.ExecuteQuery();
listColl.AddRange(from list in listCollection
where !list.Hidden
select new SPList
{
Title = list.Title,
ListGUID = list.Id.ToString(),
RootFolderServerRelativeUrl = list.RootFolder.ServerRelativeUrl,
ParentWebUrl = list.ParentWebUrl
});
}
catch (Exception ex)
{
// error log
}
return listColl;
}
public List<SPFolder> GetAllFolder(string webURL, string listName, string folderName)
{
var itemColl = new List<SPFolder>();
try
{
var currentWeb = _ctx.Site.OpenWeb(webURL);
var currentList = currentWeb.Lists.GetByTitle(listName);
var query = new CamlQuery();
if (folderName.Length > 0)
query.FolderServerRelativeUrl = folderName;
query.ViewXml = #"<View><Query><Where>
<Or>
<Eq>
<FieldRef Name='ContentType' />
<Value Type='Text'>Document Set</Value>
</Eq>
<Eq>
<FieldRef Name='ContentType' />
<Value Type='Text'>Folder</Value>
</Eq>
</Or>
</Where></Query></View>";
var listitems = currentList.GetItems(query);
_ctx.Load(listitems);
_ctx.ExecuteQuery();
itemColl.AddRange(listitems.ToList().Select(item => new SPFolder()
{
ID = Convert.ToString(item["ID"]),
UniqueID = Convert.ToString(item["GUID"]),
ListName = listName,
ParentWebUrl = webURL,
Title = Convert.ToString(item["FileLeafRef"]),
Name = "folder",
ServerRelativeUrl = Convert.ToString(item["FileRef"])
}).AsEnumerable());
}
catch (Exception ex)
{
// error log
}
return itemColl;
}
public List<SPListItem> GetAllItems(string webURL, string listName, string folderName)
{
var itemColl = new List<SPListItem>();
try
{
var currentWeb = _ctx.Site.OpenWeb(webURL);
var currentList = currentWeb.Lists.GetByTitle(listName);
var query = new CamlQuery();
if (folderName.Length > 0)
query.FolderServerRelativeUrl = folderName;
var myquery = from myitems in currentList.GetItems(query)
select myitems;
var listitems = _ctx.LoadQuery(myquery.Include(myitem => myitem["ID"],
myitem => myitem["FileLeafRef"],
myitem => myitem["Modified"],
myitem => myitem["File_x0020_Size"],
myitem => myitem["Modified_x0020_By"],
myitem => myitem["Created_x0020_By"],
myitem => myitem["FileRef"],
myitem => myitem["UniqueId"],
));
_ctx.ExecuteQuery();
foreach (var nitem in listitems.Select(item => new SPListItem
{
ID = Convert.ToString(item["ID"]),
ParentWebUrl = webURL,
Title = Convert.ToString(item["FileLeafRef"]),
Modified = item["Modified"] != null ? Convert.ToString(item["Modified"]) : string.Empty, Size = item["File_x0020_Size"] != null ? Convert.ToString(item["File_x0020_Size"]) : string.Empty,
CreatedBy = item["Created_x0020_By"] != null ? Convert.ToString(item["Created_x0020_By"]) : string.Empty,
ModifiedBy = item["Modified_x0020_By"] != null ? Convert.ToString(item["Modified_x0020_By"]) : string.Empty,
UniqueId = item["UniqueId"].ToString(),
ServerRelativeUrl = Convert.ToString(item["FileRef"]),
ListName = listName
}))
itemColl.Add(nitem);
}
catch (Exception ex)
{
// error log
}
return itemColl;
}
For this I used following reference,
http://shahjinesh11.wordpress.com/2012/06/14/net-managed-client-object-model-fetch-all-webs-libraries-items/
it may helps you Good Luck :-)
my code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var service = SPFarm.Local.Services.GetValue<SPWebService>(string.Empty);
foreach (SPWebApplication webApplication in service.WebApplications)
{
ShowSiteCollection(webApplication.Sites);
}
}
}
private void ShowSiteCollection(IEnumerable<SPSite> sites)
{
foreach (SPSite site in sites)
{
using (site)
{
var rootWeb = site.RootWeb;
var node = new TreeNode(rootWeb.Title, rootWeb.Url);
if (rootWeb.Webs.Count > 0)
{
ShowWebCollection(rootWeb.Webs, (title, url) => node.ChildNodes.Add(new TreeNode(title, url)));
}
siteCollectionTree.Nodes.Add(node);
}
}
}
private static void ShowWebCollection(SPWebCollection collection, Action<string, string> func)
{
for (var i = 0; i < collection.Count; i++)
{
var info = collection.WebsInfo[i];
func.Invoke(info.Title, info.ServerRelativeUrl);
if (collection[i].Webs.Count > 0)
{
ShowWebCollection(collection[i].Webs, func);
}
}
}
And method for getting list:
private static IEnumerable<List> GetSiteLists(string siteUrl)
{
using (var context = new ClientContext(siteUrl))
{
var query = from lists in context.Web.Lists
where !lists.Hidden
select lists;
var siteLists = context.LoadQuery(query);
context.ExecuteQuery();
return siteLists;
}
}
I don't claim, that the solution is the best, but it works. Good luck!

Automapper map custom collections

Hello. I have a list that looks like this one:
public class PagedList<T> : List<T>
{
public PagedList(IEnumerable<T> collection) : base(collection)
{ }
public int TotalItems { get; set; }
public int CurrentPage { get; set; }
public int PageSize { get; set; }
//some other properties
}
and used in repository for paging
public PagedList<TEntity> GetPaged(int page)
{
var pagedEntities = some_query;
return pagedEntities.AsPagedList(totalResults, page, pageSize);
}
The same PagedList is also used in asp mvc view models for paging.
Is it possible to map this collections using Automapper with all the properties TotalItems/CurrentPage/... ?
PagedList<DbItem> dbItems = _repository.GetPages(page);
var viewItems = new PagedList<SomeItemView>();
Mapper.Map(dbItems , viewItems);
Tahnk You !
This worked for me. Are you looking for something more generic?
public class DbItem
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ViewItem
{
public int Id { get; set; }
public string Name { get; set; }
}
public class PagedList<T>: List<T>
{
public int TotalItems { get; set; }
public int CurrentPage { get; set; }
public int PageSize { get; set; }
}
class Program
{
static void Main(string[] args)
{
MapItems();
}
public static void MapItems()
{
Mapper.CreateMap<DbItem, ViewItem>();
Mapper.CreateMap<PagedList<DbItem>, PagedList<ViewItem>>()
.AfterMap((s, d) => Mapper.Map<List<DbItem>, List<ViewItem>>(s, d));
var dbList = new PagedList<DbItem>
{
new DbItem {Id = 1, Name = "a"},
new DbItem {Id = 2, Name = "b"}
};
dbList.TotalItems = 2;
dbList.CurrentPage = 1;
dbList.PageSize = 10;
var viewList = Mapper.Map<PagedList<DbItem>, PagedList<ViewItem>>(dbList);
Console.WriteLine(viewList.TotalItems);
Console.WriteLine(viewList.CurrentPage);
Console.WriteLine(viewList.PageSize);
Console.WriteLine(viewList[0].Id + " " + viewList[0].Name);
Console.WriteLine(viewList[1].Id + " " + viewList[1].Name);
Console.ReadLine();
}
}
What you need is a custom type converter
public class PagedListConverter<TIn, TOut> : ITypeConverter<IPagedList<TIn>, IPagedList<TOut>>
{
public IPagedList<TOut> Convert(AutoMapper.ResolutionContext context)
{
var source = (IPagedList<TIn>)context.SourceValue;
var mapped = Mapper.Map<IList<TOut>>(source);
return new StaticPagedList<TOut>(mapped, source.GetMetaData());
}
}
Usage:
Mapper.CreateMap<IPagedList<Company>, IPagedList<CompanyViewModel>>().ConvertUsing<PagedListConverter<Company, CompanyViewModel>>();
For those who have faced the similar problem recently, and as an update to NoPyGod's answer, you can achieve the general mapping using ITypeConverter. According to the official documentation:
AutoMapper also supports open generic type converters with any number of generic arguments:
var configuration = new MapperConfiguration(cfg =>
cfg.CreateMap(typeof(Source<>), typeof(Destination<>)).ConvertUsing(typeof(Converter<,>)));
The closed type from Source will be the first generic argument, and the closed type of Destination will be the second argument to close Converter<,>.
So the custom type converter would be:
private class Converter<TSource, TDestination>
: ITypeConverter<PagedList<TSource>, PagedList<TDestination>>
{
public PagedList<TDestination> Convert(
PagedList<TSource> source,
PagedList<TDestination> destination,
ResolutionContext context) =>
new PagedList<TDestination>(
context.Mapper.Map<List<TSource>, List<TDestination>>(source));
/* Additional settings comes here. */
}
And then register it:
this.CreateMap(typeof(PagedList<>), typeof(PagedList<>)).ConvertUsing(typeof(Converter<,>));

Deserialization of XDocument doesn't work

I have this code:
[Serializable]
[XmlRoot("ISO_CCY_CODES")]
public class IsoCurrencyCodes
{
public IsoCurrencyCodes()
{
IsoCodes = new List<IsoCurrencyCode>();
}
public IsoCurrencyCodes(List<IsoCurrencyCode> isoCodes)
{
IsoCodes = isoCodes;
}
[XmlArrayItem("ISO_CURRENCY")]
public List<IsoCurrencyCode> IsoCodes { get; set; }
public static IEnumerable<IsoCurrencyCode> Get()
{
var doc = XDocument.Parse(XmlStringIsoCodes.XmlSource.Replace("\r\n", ""));
var res = doc.Deserialize<IsoCurrencyCodes>();
return res.IsoCodes;
}
}
[Serializable]
[XmlRoot("ISO_CURRENCY")]
public class IsoCurrencyCode
{
public IsoCurrencyCode()
{
}
[XmlElement(ElementName = "ENTITY")]
public string Entity { get; set; }
[XmlElement(ElementName = "CURRENCY")]
public string Currency { get; set; }
[XmlElement(ElementName = "ALPHABETIC_CODE")]
public string Alpha_Code3 { get; set; }
[XmlElement(ElementName = "NUMERIC_CODE")]
public int NumCode { get; set; }
[XmlElement(ElementName = "MINOR_UNIT")]
public string MinorUnit { get; set; }
}
And this code, for deserialization:
public static XDocument Serialize<T>(this T source)
{
var ser = new XmlSerializer(source.GetType());
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
{
ser.Serialize(writer, source);
}
return XDocument.Parse(sb.ToString());
}
public static T Deserialize<T>(this XDocument xmlDocument)
{
var xmlSerializer = new XmlSerializer(typeof (T));
using (var reader = xmlDocument.CreateReader())
return (T) xmlSerializer.Deserialize(reader);
}
This is the XML source
But deserialization doesn't work. Please help.
Thanks!
I believe you only want to use XMLArray if you have a collection element for all of the items to sit underneath. For example here it could be ISO_CURRENCIES. I'm assuming you can't change the source in this case, so just use this instead:
[XmlElement("ISO_CURRENCY")]
public List<IsoCurrencyCode> IsoCodes { get; set; }
You should find that works.
Additionally, if you find you have further problems in getting the deserialization classes right, you can have them autogenerated for you from the XML and then you can take a look at the code that is created:
xsd source.xml
xsd source.xsd /c
This will create source.cs which you can then use in your project or adapt for your own uses.
As a further note, you'll find you can't use int for Minor_Unit as it's nullable (look at ANTARCTICA). You can't deserialize straight to an int?, so you'll either have to make it a string or go via another property, look at this question for more information.

Resources