Quantcast
Channel: CamlJs: SharePoint JavaScript Caml Builder
Viewing all 199 articles
Browse latest View live

New Post: Bower and CommonJS

$
0
0
Hi

Thanks for the library!

Would it be possible to make it available on bower?
Support for browserify would also be great.

New Post: Any way to specify OrderBy() without Where() ?

$
0
0
I would like to 2nd this request. I need to be able to order every item in a list. Right now I have make the query by hand or fake it by selecting some ridiculous never true value for a field to make the query.

New Post: Progressively Build up my CAML

$
0
0
This example from Omlin is what I needed. I think if I had not seen this discussion I would have given up on this tool. I think this example should be put in on the home page.

Created Unassigned: Get extra And in resultant query [8]

$
0
0
I am trying to do use conditional logic to register multiple And and Or statements. For the most part this working well except when the FilterBy if evaluates to true. In that scenario I get an extra And in the CAML query that causes the query to fail. If there is a better way to go about what I am trying to accomplish I would appreciate the input.

```
var camlB = new CamlBuilder();
var caml;

if (PersonalizationScope && PersonalizationScope.length > 0) {
caml = camlB.Where()
.TextField("ServiceLocation").In(PersonalizationScope);
}
else{
caml = camlB.Where()
.TextField("ServiceLocation").IsNotNull(PersonalizationScope);

}

if (FilterBy > 0) {
caml.And()
.LookupField("CategoryLookup").Id().EqualTo(FilterBy);
}

if (searchTerm) {
if (contentType == FEATURED_CONTENT_CONSTANTS.NewsContentType) {
caml.And()
.TextField('FullNewsStory').Contains(searchTerm)
.Or()
.TextField('PreviewDescription').Contains(searchTerm)
.Or()
.TextField('Title').Contains(searchTerm);
}
else if (contentType == fea.FeaturedContentType) {
caml.And()
.TextField('Title').Contains(searchTerm)
.Or()
.TextField('PreviewDescription').Contains(searchTerm)
}
}

whereCondition = caml.ToString();
```

This generates the following XML when FilterBy evaluates to false. This is valid CAML.
```
<Where>
<And>
<In>
<FieldRef Name="Test" />
<Values>
<Value Type="Text">Atlanta</Value>
<Value Type="Text">North & UK</Value>
</Values>
</In>
<Or>
<Contains>
<FieldRef Name="FullNewsStory" />
<Value Type="Text">dui</Value>
</Contains>
<Or>
<Contains>
<FieldRef Name="PreviewDescription" />
<Value Type="Text">dui</Value>
</Contains>
<Contains>
<FieldRef Name="Title" />
<Value Type="Text">dui</Value>
</Contains>
</Or>
</Or>
</And>
</Where>
```

This is the XML that is generated by FilterBy evaluates to true. Notice the extra And in the beginning of the Where. This is invalid CAML.

```
<Where>
<And>
<And>
<In>
<FieldRef Name="Test" />
<Values>
<Value Type="Text">Atlanta</Value>
<Value Type="Text">North & UK</Value>
</Values>
</In>
<Eq>
<FieldRef Name="CategoryLookup" LookupId="True" />
<Value Type="Integer">5</Value>
</Eq>
<Or>
<Contains>
<FieldRef Name="FullNewsStory" />
<Value Type="Text">du</Value>
</Contains>
<Or>
<Contains>
<FieldRef Name="PreviewDescription" />
<Value Type="Text">du</Value>
</Contains>
<Contains>
<FieldRef Name="Title" />
<Value Type="Text">du</Value>
</Contains>
</Or>
</Or>
</And>
</And>
</Where>
```

Side note, if I add the And() function call so that it is part of the first If statement then the CAML is generated correctly. I suspect that whatever is being returned by the .Where() is somehow different than what is returned by the And() and that is what causes the issue.

Commented Unassigned: Get extra And in resultant query [8]

$
0
0
I am trying to do use conditional logic to register multiple And and Or statements. For the most part this working well except when the FilterBy if evaluates to true. In that scenario I get an extra And in the CAML query that causes the query to fail. If there is a better way to go about what I am trying to accomplish I would appreciate the input.

```
var camlB = new CamlBuilder();
var caml;

if (PersonalizationScope && PersonalizationScope.length > 0) {
caml = camlB.Where()
.TextField("ServiceLocation").In(PersonalizationScope);
}
else{
caml = camlB.Where()
.TextField("ServiceLocation").IsNotNull(PersonalizationScope);

}

if (FilterBy > 0) {
caml.And()
.LookupField("CategoryLookup").Id().EqualTo(FilterBy);
}

if (searchTerm) {
if (contentType == FEATURED_CONTENT_CONSTANTS.NewsContentType) {
caml.And()
.TextField('FullNewsStory').Contains(searchTerm)
.Or()
.TextField('PreviewDescription').Contains(searchTerm)
.Or()
.TextField('Title').Contains(searchTerm);
}
else if (contentType == fea.FeaturedContentType) {
caml.And()
.TextField('Title').Contains(searchTerm)
.Or()
.TextField('PreviewDescription').Contains(searchTerm)
}
}

whereCondition = caml.ToString();
```

This generates the following XML when FilterBy evaluates to false. This is valid CAML.
```
<Where>
<And>
<In>
<FieldRef Name="Test" />
<Values>
<Value Type="Text">Atlanta</Value>
<Value Type="Text">North & UK</Value>
</Values>
</In>
<Or>
<Contains>
<FieldRef Name="FullNewsStory" />
<Value Type="Text">dui</Value>
</Contains>
<Or>
<Contains>
<FieldRef Name="PreviewDescription" />
<Value Type="Text">dui</Value>
</Contains>
<Contains>
<FieldRef Name="Title" />
<Value Type="Text">dui</Value>
</Contains>
</Or>
</Or>
</And>
</Where>
```

This is the XML that is generated by FilterBy evaluates to true. Notice the extra And in the beginning of the Where. This is invalid CAML.

```
<Where>
<And>
<And>
<In>
<FieldRef Name="Test" />
<Values>
<Value Type="Text">Atlanta</Value>
<Value Type="Text">North & UK</Value>
</Values>
</In>
<Eq>
<FieldRef Name="CategoryLookup" LookupId="True" />
<Value Type="Integer">5</Value>
</Eq>
<Or>
<Contains>
<FieldRef Name="FullNewsStory" />
<Value Type="Text">du</Value>
</Contains>
<Or>
<Contains>
<FieldRef Name="PreviewDescription" />
<Value Type="Text">du</Value>
</Contains>
<Contains>
<FieldRef Name="Title" />
<Value Type="Text">du</Value>
</Contains>
</Or>
</Or>
</And>
</And>
</Where>
```

Side note, if I add the And() function call so that it is part of the first If statement then the CAML is generated correctly. I suspect that whatever is being returned by the .Where() is somehow different than what is returned by the And() and that is what causes the issue.
Comments: I'd recommend using __All__ and __Any__ and __CamlBuilder.Expression__ for composing dynamic queries. This will simplify the code and make it more visual. ``` var PersonalizationScope = []; var FilterBy = 1; var searchTerm = 'something'; var FEATURED_CONTENT_CONSTANTS = { NewsContentType: 'test' }; var contentType = 'test'; var fea = { FeaturedContentType: 'testF' }; var conditions = []; if (PersonalizationScope && PersonalizationScope.length > 0) conditions.push(CamlBuilder.Expression().TextField("ServiceLocation").In(PersonalizationScope)); else conditions.push(CamlBuilder.Expression().TextField("ServiceLocation").IsNotNull()); if (FilterBy > 0) conditions.push(CamlBuilder.Expression().LookupField("CategoryLookup").Id().EqualTo(FilterBy)); if (searchTerm) { if (contentType == FEATURED_CONTENT_CONSTANTS.NewsContentType) { conditions.push(CamlBuilder.Expression() .TextField('FullNewsStory').Contains(searchTerm) .Or() .TextField('PreviewDescription').Contains(searchTerm) .Or() .TextField('Title').Contains(searchTerm)); } else if (contentType == fea.FeaturedContentType) { conditions.push(CamlBuilder.Expression() .TextField('Title').Contains(searchTerm) .Or() .TextField('PreviewDescription').Contains(searchTerm)); } } var query = new CamlBuilder().Where().All(conditions).ToString(); ``` This generates the following: ``` <Where> <And> <IsNotNull> <FieldRef Name="ServiceLocation" /> </IsNotNull> <And> <Eq> <FieldRef Name="CategoryLookup" LookupId="True" /> <Value Type="Integer">1</Value> </Eq> <Or> <Contains> <FieldRef Name="FullNewsStory" /> <Value Type="Text">something</Value> </Contains> <Or> <Contains> <FieldRef Name="PreviewDescription" /> <Value Type="Text">something</Value> </Contains> <Contains> <FieldRef Name="Title" /> <Value Type="Text">something</Value> </Contains> </Or> </Or> </And> </And> </Where> ``` Also there's a couple mistakes in how you use the CamlBuilder, in order to not to make those I really recommend using the CamlJs Console, you can save like hours of development time by using it.

Commented Unassigned: Get extra And in resultant query [8]

$
0
0
I am trying to do use conditional logic to register multiple And and Or statements. For the most part this working well except when the FilterBy if evaluates to true. In that scenario I get an extra And in the CAML query that causes the query to fail. If there is a better way to go about what I am trying to accomplish I would appreciate the input.

```
var camlB = new CamlBuilder();
var caml;

if (PersonalizationScope && PersonalizationScope.length > 0) {
caml = camlB.Where()
.TextField("ServiceLocation").In(PersonalizationScope);
}
else{
caml = camlB.Where()
.TextField("ServiceLocation").IsNotNull(PersonalizationScope);

}

if (FilterBy > 0) {
caml.And()
.LookupField("CategoryLookup").Id().EqualTo(FilterBy);
}

if (searchTerm) {
if (contentType == FEATURED_CONTENT_CONSTANTS.NewsContentType) {
caml.And()
.TextField('FullNewsStory').Contains(searchTerm)
.Or()
.TextField('PreviewDescription').Contains(searchTerm)
.Or()
.TextField('Title').Contains(searchTerm);
}
else if (contentType == fea.FeaturedContentType) {
caml.And()
.TextField('Title').Contains(searchTerm)
.Or()
.TextField('PreviewDescription').Contains(searchTerm)
}
}

whereCondition = caml.ToString();
```

This generates the following XML when FilterBy evaluates to false. This is valid CAML.
```
<Where>
<And>
<In>
<FieldRef Name="Test" />
<Values>
<Value Type="Text">Atlanta</Value>
<Value Type="Text">North & UK</Value>
</Values>
</In>
<Or>
<Contains>
<FieldRef Name="FullNewsStory" />
<Value Type="Text">dui</Value>
</Contains>
<Or>
<Contains>
<FieldRef Name="PreviewDescription" />
<Value Type="Text">dui</Value>
</Contains>
<Contains>
<FieldRef Name="Title" />
<Value Type="Text">dui</Value>
</Contains>
</Or>
</Or>
</And>
</Where>
```

This is the XML that is generated by FilterBy evaluates to true. Notice the extra And in the beginning of the Where. This is invalid CAML.

```
<Where>
<And>
<And>
<In>
<FieldRef Name="Test" />
<Values>
<Value Type="Text">Atlanta</Value>
<Value Type="Text">North & UK</Value>
</Values>
</In>
<Eq>
<FieldRef Name="CategoryLookup" LookupId="True" />
<Value Type="Integer">5</Value>
</Eq>
<Or>
<Contains>
<FieldRef Name="FullNewsStory" />
<Value Type="Text">du</Value>
</Contains>
<Or>
<Contains>
<FieldRef Name="PreviewDescription" />
<Value Type="Text">du</Value>
</Contains>
<Contains>
<FieldRef Name="Title" />
<Value Type="Text">du</Value>
</Contains>
</Or>
</Or>
</And>
</And>
</Where>
```

Side note, if I add the And() function call so that it is part of the first If statement then the CAML is generated correctly. I suspect that whatever is being returned by the .Where() is somehow different than what is returned by the And() and that is what causes the issue.
Comments: Oh man, that is much easier! I didn't see an example of using this approach in the documentation, you should definitely add it! Super nice, and thanks a ton!

New Post: ModStat support

$
0
0
Trying to create rule like
<Eq><FieldRef Name='_ModerationStatus' /><Value Type='ModStat'>3</Value></Eq>
but there is no support to ModStat Value Type. Any good workarounds to change the value type keeping in mind I'm dynamically pushing the Expressions?

E.g.,
camlExpressions.push(CamlBuilder.FromXml(CamlBuilder.Expression().IntegerField("_ModerationStatus").EqualTo(3).ToString().replace("Integer", "ModStat")));        
doesn't work as FromXml isn't meant for Expressions.

New Post: ModStat support

$
0
0
Looks like one workaround is
        var modStat = CamlBuilder.Expression().IntegerField("_ModerationStatus").EqualTo(3);
        modStat.builder.tree[2].ValueType = "ModStat";
        camlExpressions.push(modStat);

New Post: Pull request: ChoiceField type and ComputedField type added

$
0
0
I've added two field types: Choice and Computed. The last one is for querying Content Type.
FieldExpression.prototype.ChoiceField = function (internalName) {
            return new FieldExpressionToken(this.builder, internalName, "Choice");
        };
        /** Specifies that a condition will be tested against the field with the specified internal name, and the type of this field is Computed */
        FieldExpression.prototype.ComputedField = function (internalName) {
            return new FieldExpressionToken(this.builder, internalName, "Computed");
        };

New Post: Pull request: ChoiceField type and ComputedField type added

$
0
0
Hi,

Thanks, I'll incorporate this into the next release!

Source code checked in, #024bb43f0b90e159b1cca0003ccbfc869f7b5a8e

$
0
0
Added ModStatField and fixed bug with BooleanField

Source code checked in, #92d73ba4fd93806295da4c2a1267cf7a0b30ac94

$
0
0
Added sinon and some ToCamlQuery tests.

Created Release: Release 2.7

$
0
0
Changes:
  • Added ModStatField
  • Bugfixes

Updated Release: Release 2.7

$
0
0

Changes

  • Added ModStatField for working with moderation status (Approved, Rejected, Pending)
  • Bugfixes

ModStatField example

Example below will show titles of all items in "Documents" library that are rejected:

    var camlQuery = new CamlBuilder().Where()
        .ModStatField("_ModerationStatus").IsRejected()
        .ToCamlQuery();

    var listItems = context.get_web().get_lists().getByTitle("Documents").getItems(camlQuery);
    context.load(listItems);
    context.executeQueryAsync(function() {
        var e = listItems.getEnumerator();
        while (e.moveNext())
        {
            console.log(e.get_current.get_title());
        }
    })

Updated Release: Release 2.7 (Oct 07, 2016)

$
0
0

Changes

  • Added ModStatField for working with moderation status (Approved, Rejected, Pending)
  • Bugfixes

ModStatField example

Example below will show titles of all items in "Documents" library that are rejected:

    var camlQuery = new CamlBuilder().Where()
        .ModStatField("_ModerationStatus").IsRejected()
        .ToCamlQuery();

    var listItems = context.get_web().get_lists().getByTitle("Documents").getItems(camlQuery);
    context.load(listItems);
    context.executeQueryAsync(function() {
        var e = listItems.getEnumerator();
        while (e.moveNext())
        {
            console.log(e.get_current.get_title());
        }
    })


Updated Release: Release 2.7 (Oct 07, 2016)

$
0
0

Changes

  • Added ModStatField for working with moderation status (Approved, Rejected, Pending)
  • Bugfixes

ModStatField example

Example below will show titles of all items in "Documents" library that are rejected:

    var context = SP.ClientContext.get_current();
    var list = context.get_web().get_lists().getByTitle("Documents");

    var camlQuery = new CamlBuilder().Where()
        .ModStatField("_ModerationStatus").IsRejected()
        .ToCamlQuery();

    var listItems = list.getItems(camlQuery);
    context.load(listItems);
    context.executeQueryAsync(function() {
        var e = listItems.getEnumerator();
        while (e.moveNext())
        {
            console.log(e.get_current.get_title());
        }
    })

Released: Release 2.7 (Oct 07, 2016)

$
0
0

Changes

  • Added ModStatField for working with moderation status (Approved, Rejected, Pending)
  • Fixed problem with boolean fields EqualTo. Code e.g. BooleanField("field").EqualTo(someBoolVar) is now working correctly.

ModStatField example

Example below will show titles of all items in "Documents" library that are rejected:

    var context = SP.ClientContext.get_current();
    var list = context.get_web().get_lists().getByTitle("Documents");

    var camlQuery = new CamlBuilder().Where()
        .ModStatField("_ModerationStatus").IsRejected()
        .ToCamlQuery();

    var listItems = list.getItems(camlQuery);
    context.load(listItems);
    context.executeQueryAsync(function() {
        var e = listItems.getEnumerator();
        while (e.moveNext())
        {
            console.log(e.get_current.get_title());
        }
    })

Updated Release: Release 2.7 (Oct 07, 2016)

$
0
0

Changes

  • Added ModStatField for working with moderation status (Approved, Rejected, Pending)
  • Fixed problem with boolean fields EqualTo. Code e.g. BooleanField("field").EqualTo(someBoolVar) is now working correctly.

ModStatField example

Example below will show titles of all items in "Documents" library that are rejected:

    var context = SP.ClientContext.get_current();
    var list = context.get_web().get_lists().getByTitle("Documents");

    var camlQuery = new CamlBuilder().Where()
        .ModStatField("_ModerationStatus").IsRejected()
        .ToCamlQuery();

    var listItems = list.getItems(camlQuery);
    context.load(listItems);
    context.executeQueryAsync(function() {
        var e = listItems.getEnumerator();
        while (e.moveNext())
        {
            console.log(e.get_current.get_title());
        }
    })

Updated Wiki: Home

$
0
0

Project Description

Simplifies creation of SharePoint CAML queries for client-side scripts. Can be used with either SharePoint Client Object Model or SPServices.

Nuget:

PM> Install-Package CamlJs

TypeScript definitions:

PM> Install-Package camljs.TypeScript.DefinitelyTyped

What's new in Release 2.7

    1. New type of field - ModStatField
    2. Fixed bug with boolean field EqualTo operation

What's new in Release 2.6

      1. Now it is possible to use CamlJs for modifying existing CAML queries:
        • FromXml method will create a CamlBuilder object from existing CAML string
        • ReplaceWhere method allows to replace <Where> clause with one generated by CamlJs
        • ModifyWhere().AppendAnd() will add new conditions to existing query using "And" operator
        • ModifyWhere().AppendOr() will add new conditions to existing query using "Or" operator

        Example:

      2. Added Query().GroupBy(...) and Query().OrderBy(...)

 

Check out CamlJs-Console!

I created a Chrome extension for instant testing CamlJs queries against real lists,CamlJs-Console. The extension is open source and free. Available via Web Store or alternatively you can install it from the source code (see docs on GitHub).

What's new in Release 2.5

View element

View element is added! Scope attribute, ViewFields, Joins and ProjectedFields are supported. Joining lists via CamlJs is very easy. Here's the example:

var query = new CamlBuilder()
    .View(["Title","Country","Population"])
    .LeftJoin("Country","Country").Select("People","Population")
    .Query()
    .Where()
    .NumberField("Population").LessThan(10)
    .ToString();

Intellisense helps understanding the parameters:

And one more screenshot of intellisense:

So as you see, really simple: Join listName as Alias, Select Field as Alias, Select Field as Alias, etc. Then, use fields aliases in the main query. That's it! Corresponding Joins and ProjectedFields elements are generated automatically.

So the resulting generated CAML query will be the following:

<View><ViewFields><FieldRefName="Title"/><FieldRefName="Country"/><FieldRefName="Population"/></ViewFields><Joins><JoinType="LEFT"ListAlias="Country"><Eq><FieldRefName="Country"RefType="ID"/><FieldRefName="ID"List="Country"/></Eq></Join></Joins><ProjectedFields><FieldShowField="People"Type="Lookup"Name="Population"List="Country"/></ProjectedFields><Query><Where><Lt><FieldRefName="Population"/><ValueType="Number">10</Value></Lt></Where></Query></View>

No dependencies

CamlJs was dependent on some SharePoint components (Sys.StringBuilder and SP.XmlWriter). But many people had problems with that, so now CamlJs doesn't have any dependencies.

This enables opportunity to run CamlJs standalone, e.g. in SharePoint Apps without including heavy SP javascripts; and also to use CamlJs in SharePoint 2007. Though please remember that some CAML Query elements (e.g. <In>) were added only in SP2010.

Migration from 2.0 to 2.5

Please remember that some fields were marked as DEPRECATED in Release 2.0. In version 2.5, previously marked LookupIdField is removed. In next versions, the process will be continued.

If you're still using LookupIdField, replace it like this:

Old code example:

.LookupIdField("MyLookup").EqualTo(5)

Replace with:

.LookupField("MyLookup").Id().EqualTo(5)

ToCamlQuery()

Added ToCamlQuery method, that can be to finalize the query. But instead of string, ToCamlQuery will produce a ready-to-use SP.CamlQuery object, which you can then pass into list.getItems method.

Example project

Example project is now a SharePoint-hosted app with a simple interactive demo:

UserMultiField and LookupMultiField

UserMultiField and LookupMultiField weren't much tested in previous release, but now in 2.5 they are tested through and significantly improved. Now instead old EqualTo, NotEqualTo, Includes and NotIncludes operations (these are marked DEPRECATED), single operation "IncludesSuchItemThat" added.

 

So now it is possible to check condition against Id or against a value, cast to a specified type (same as with single-value lookups):

Internally, CAML Query is identical for MultiLookup and single-value Lookup columns, but hopefully this minor syntax improvement will help people better understand how SharePoint interprets this query.

---------------- end of release 2.5 news -------------

Basics

To start with, let's assume we need to fetch all Google-related letters from some mailbox list, using SharePoint Client Object Model. To generate the corresponding query using Caml Builder, you could use following javascript code:

var camlBuilder = new CamlBuilder();

    var caml = camlBuilder.Where()
        .TextField("Email").EqualTo("support@google.com")
        .Or()
        .TextField("Email").EqualTo("plus@google.com")
        .Or()
        .TextField("Title").BeginsWith("[Google]")
        .Or()
        .TextField("Content").Contains("Google")
        .ToString();

This will generate expected CAML:

<Where><Or><Eq><FieldRefName="Email"/><ValueType="Text">support@google.com</Value></Eq><Or><Eq><FieldRefName="Email"/><ValueType="Text">plus@google.com</Value></Eq><Or><BeginsWith><FieldRefName="Title"/><ValueType="Text">[Google]</Value></BeginsWith><Contains><FieldRefName="Content"/><ValueType="Text">Google</Value></Contains></Or></Or></Or></Where>

, which then could be used in SP.CamlQuery.

Very good so far, and have a look at some other examples!

First of all, cannot resist to mention, that CamlBuilder covers almost all Query elements, described at MSDN.

For example, seldom used Membership element:

var caml = camlBuilder.Where()
        .UserField("AssignedTo").EqualToCurrentUser()
        .Or()
        .UserField("AssignedTo").IsInCurrentUserGroups()
        .GroupBy("ProductTitle")
        .OrderBy("Priority").ThenBy("Title")
        .ToString();

This code will generate following CAML:

<Where><Or><Eq><FieldRefName="AssignedTo"/><ValueType="Integer"><UserID/></Value></Eq><MembershipType="CurrentUserGroups"><FieldRefName="AssignedTo"/></Membership></Or></Where><GroupBy><FieldRefName="ProductTitle"/></GroupBy><OrderBy><FieldRefName="Priority"/><FieldRefName="Title"/></OrderBy>

The last example at this section:

    caml = camlBuilder.Where()
        .LookupField("Category").Id().In([2, 3, 10])
        .And()
        .DateField("ExpirationDate").LessThanOrEqualTo(CamlBuilder.CamlValues.Now)
        .OrderByDesc("ExpirationDate")
        .ToString()

As you see, the code is pretty clean and readable. The resulting CAML is much more awkward, especially if you imagine it in javascript strings dress, without indentation and highlighting...

<Where><And><In><FieldRefName="Category"LookupId="True"/><Values><ValueType="Integer">2</Value><ValueType="Integer">3</Value><ValueType="Integer">10</Value></Values></In><Leq><FieldRefName="ExpirationDate"/><ValueType="Date"><Now/></Value></Leq></And></Where><OrderBy><FieldRefName="ExpirationDate"Ascending="False"/></OrderBy>

Usability

CamlBuilder is not only readable and simple, but it also provides rich intellisense and inline documentation:

This will help to catch a bunch of errors when writing code, and surely prevent from typos and misunderstandings, so the benefits could be really magnificient!

Intellisense and inline docs are even better if you use CamlJs with TypeScript.

Contribute

Any contributions are highly appreciated!

New Post: Is there any equivalent in C#

$
0
0
Hi

I have used CamlJs couple of times and feeling quite comfortable.
Is there any equivalent for c# available?
Viewing all 199 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>