I am creating a webservice using asp.net 4.0.
I have created a asmx file and creating a User.cs Class. It has 8 Properties.
I have return a service with json format.
If the userlogin is true i need to return all the properties of user.cs, if it's fail i need to return only 2 property.
How to achieve it.
User login is true. It will return all
{"message":"valid user","BranchId":1,"BranchName":"My branch Name","Id":1,"Name":"admin","Password":"admin","RoleId":1,"Status":1}
User login is failed i need to retun only message and Status. but it will return all like as foloows
{"message":"username or password is invalid","BranchId":0,"BranchName":null,"Id":0,"Name":null,"Password":null,"RoleId":0,"Status":0}
I have google it and get the following Link. How to use it based on my login status condition.
If i have used [ScriptIgnore] in my property it will ignore property both case. I need to ignore property when login failed.
My properties like this
// Properties
public int BranchId
{
get { return _BranchId; }
set { if (_BranchId != value) { _BranchId = value; } }
}
public string BranchName
{
get { return _BranchName; }
set { _BranchName = value; }
}
private String _message;
public String message
{
get { return _message; }
set { _message = value; }
}
My webservice
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public void appLogin(String userName, String passWord)
{
Admin_AppUserBLL objusr = Admin_AppUserBLL.GetAdmin_AppUserBLL(userName);
string strResponse = "";
if (objusr != null)
{
if (objusr.Password == passWord)
{
objusr.message = "valid username";
strResponse = new JavaScriptSerializer().Serialize(objusr);
}
}
else
{
objusr = new Admin_AppUserBLL();
objusr.message = "username or password is invalid";
strResponse = new JavaScriptSerializer().Serialize(objusr);
}
Context.Response.Clear();
Context.Response.ContentType = "application/json";
Context.Response.AddHeader("content-length", strResponse.Length.ToString());
Context.Response.Flush();
Context.Response.Write(strResponse);
}
Add following attribute on your property and also make it nullable by using "?"
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "BranchId")]
public int? BranchId{ get; set; }
It will ignore if value will be null and also json does not contain these peoperties.
Add reference in Newtonsoft
using Newtonsoft.Json;
while serialize the object
string strResponse = JsonConvert.SerializeObject(objusr, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
it will avoid null value property
Related
So I am very new to the whole .NET world, so I could very well have some terminology off. I was asked to help with making some changes to this code because I've helped with some other dev work (entirely different systems). Anyway, I can't even get it to run on my test system to begin the actual work - yet they are already using this code in production so I'm assuming it's just an inconsistency in my setup. Either way though I'm trying to drill down into the code to both learn it better and hopefully understand what could be going wrong with my system.
So this API does not have a front end, all of the testing is being done from Postman. It's supposed to post a request with an XML body to a function that then reads the XML and retrieves data. For whatever reason the request that is passed in always comes up NULL, though I think I verified that Postman is submitting the data because I tried the third answer here: Getting raw POST data from Web API method and I do see the full body of the request then.
Here is the method it is posting to:
[Route("summary")]
[ResponseType(typeof(SummarySearchResponseType))]
public IHttpActionResult PostSummary([FromBody] SummarySearchRequestType req)
{
try
{
var response = _searchService.GetSummary(req);
if (response == null)
{
return BadRequest();
}
return Ok(response);
}
catch
{
return StatusCode(System.Net.HttpStatusCode.InternalServerError);
}
}
Here is that SearchService function:
public SummarySearchResponseType GetSummary(SummarySearchRequestType request)
{
Serilog.Log.Information("GetSummary request = {0}", request);
// Validate required fields in request
if (request == null)
{
Serilog.Log.Logger.Warning("One or more required search fields are missing");
return null;
}
if (string.IsNullOrEmpty(request.ClientNumber))
{
Serilog.Log.Logger.Warning("Missing required search field 'ClientNumber'");
return null;
}
if (request.LossDate == null)
{
Serilog.Log.Logger.Warning("Missing required search field 'LossDate'");
return null;
}
var response = new SummarySearchResponseType
{
RequestID = request.RequestID
};
try
{
using (IMultipleResults sprocResults = _dataContext.UspGetDetailedResponse(
request.ClientNumber,
request.PolicyNumber,
request.PolicySuffix,
request.ClientAccountNum,
request.LossDate.ToShortDateString(),
request.PolicyType,
request.LineCode,
request.AgencyCode,
request.Searchtype,
request.Lob,
request.InsuredSearch?.FirstName,
request.InsuredSearch?.LastName,
request.InsuredSearch?.FullName,
request.InsuredSearch?.DBAName,
request.InsuredSearch?.Address.Address1,
request.InsuredSearch?.Address.Address2,
request.InsuredSearch?.Address.City,
request.InsuredSearch?.Address.State,
request.InsuredSearch?.Address.PostalCode,
request.InsuredSearch?.Address.County,
request.InsuredSearch?.Address.Country,
request.InsuredSearch?.ClientAccountnumber,
request.InsuredSearch?.Email,
request.InsuredSearch?.Phone,
request.InsuredSearch?.Comment,
request.RiskUnitSearch?.RiskUnitID,
request.RiskUnitSearch?.RiskUnitName,
request.RiskUnitSearch?.LocationSearch?.BuildingID,
request.RiskUnitSearch?.LocationSearch?.Address?.Address1,
request.RiskUnitSearch?.LocationSearch?.Address?.Address2,
request.RiskUnitSearch?.LocationSearch?.Address?.City,
request.RiskUnitSearch?.LocationSearch?.Address?.State,
request.RiskUnitSearch?.LocationSearch?.Address?.PostalCode,
request.RiskUnitSearch?.LocationSearch?.Address?.County,
request.RiskUnitSearch?.LocationSearch?.Address?.Country,
request.RiskUnitSearch?.VehicleSearch.VIN,
request.RiskUnitSearch?.VehicleSearch.Year,
request.RiskUnitSearch?.VehicleSearch.Make))
{
// Policies
//
var result1 = sprocResults.GetResult<UspGetDetailedResponseResult1>();
var policies = _mapper.Map<IEnumerable<PolicyType>>(result1).ToArray();
// Insured
//
var result2 = sprocResults.GetResult<UspGetDetailedResponseResult2>();
var insured = _mapper.Map<IEnumerable<ParticipantType>>(result2).ToArray();
//Risk Unit
//
var result3 = sprocResults.GetResult<UspGetDetailedResponseResult3>();
var riskUnits = _mapper.Map<IEnumerable<RiskUnitType>>(result3).ToArray();
// Attach Participants and RiskUnits to Policies via PolicyNumber
//
policies.ToList().ForEach(p =>
{
p.Participants = insured.Where(i => i.PolicyNumber == p.PolicyNumber).ToArray();
p.RiskUnits = riskUnits.Where(i => i.PolicyNumber == p.PolicyNumber).ToArray();
});
response.Policies = policies;
response.PolicyCnt = policies.Length.ToString();
Serilog.Log.Information("GetSummary response = {0}", response);
return response;
}
}
catch (Exception ex)
{
Serilog.Log.Error(ex, $"{ex}", ex);
throw ex;
}
}
And here is the SummarySearchRequestType:
public partial class SummarySearchRequestType
{
public override string ToString()
{
XmlSerializer responseSerializer = new XmlSerializer(this.GetType());
using (StringWriter responseWriter = new StringWriter())
{
responseSerializer.Serialize(responseWriter, this);
var xmlResponse = responseWriter.ToString();
return xmlResponse;
}
}
}
And the rest of it:
public partial class SummarySearchRequestType {
private string requestIDField;
private string clientNumberField;
private string policyNumberField;
private string policySuffixField;
private string clientAccountNumField;
private System.DateTime lossDateField;
private bool lossDateFieldSpecified;
private string policyTypeField;
private string lineCodeField;
private InsuredSearchType insuredSearchField;
private RiskUnitSearchType riskUnitSearchField;
private string agencyCodeField;
private string searchtypeField;
private string lobField;
/// <remarks/>
public string RequestID {
get {
return this.requestIDField;
}
set {
this.requestIDField = value;
}
}
/// <remarks/>
public string ClientNumber {
get {
return this.clientNumberField;
}
set {
this.clientNumberField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://sedgwickcms.com/claims/entities/Policy/v1310")]
public string PolicyNumber {
get {
return this.policyNumberField;
}
set {
this.policyNumberField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://sedgwickcms.com/claims/entities/Policy/v1310")]
public string PolicySuffix {
get {
return this.policySuffixField;
}
set {
this.policySuffixField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://sedgwickcms.com/claims/entities/Policy/v1310")]
public string ClientAccountNum {
get {
return this.clientAccountNumField;
}
set {
this.clientAccountNumField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="date")]
public System.DateTime LossDate {
get {
return this.lossDateField;
}
set {
this.lossDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool LossDateSpecified {
get {
return this.lossDateFieldSpecified;
}
set {
this.lossDateFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://sedgwickcms.com/claims/entities/Policy/v1310")]
public string PolicyType {
get {
return this.policyTypeField;
}
set {
this.policyTypeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://sedgwickcms.com/claims/entities/Policy/v1310")]
public string LineCode {
get {
return this.lineCodeField;
}
set {
this.lineCodeField = value;
}
}
/// <remarks/>
public InsuredSearchType InsuredSearch {
get {
return this.insuredSearchField;
}
set {
this.insuredSearchField = value;
}
}
/// <remarks/>
public RiskUnitSearchType RiskUnitSearch {
get {
return this.riskUnitSearchField;
}
set {
this.riskUnitSearchField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://sedgwickcms.com/claims/entities/Policy/v1310")]
public string AgencyCode {
get {
return this.agencyCodeField;
}
set {
this.agencyCodeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://sedgwickcms.com/claims/entities/Policy/v1310")]
public string Searchtype {
get {
return this.searchtypeField;
}
set {
this.searchtypeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://sedgwickcms.com/claims/entities/Policy/v1310")]
public string Lob {
get {
return this.lobField;
}
set {
this.lobField = value;
}
}
}
And in Postman I'm sending a post to the server with this raw XML body:
<?xml version="1.0" encoding="utf-8" ?><SummarySearchRequest xmlns="***">
<RequestID>***</RequestID> <ClientNumber>***</ClientNumber> <LossDate>***</LossDate> <PolicyNumber xmlns="***">***</PolicyNumber>
</SummarySearchRequest>
NOTE - I replaced specific data with ***.
Postman is hitting the server, and like I said I was able to verify based on that other post that actual data is getting to the server, but somewhere it is not setting the object properly (or something else). This is running on a VM of windows 11, through IIS Express in Visual Studio which automatically serves the https on port 44375 if that matters. I'd appreciate any insight into what could be the issue, if you need any more information please let me know - I do not understand .NET well yet. Thank you!
I want to return a JSON object from a c# webmethod if i use return i have an error "recussive reference found". So i decided to use newtonsoft serialize but the returned object are in double quote. {d:"my json"} and didn't work.
I try to use this code :
[WebMethod(EnableSession = true)]
public static void RecordList(int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
{
string error;
var result = DataTools.Data("select id_individu,nom_indiv from individu limit 10",
WebConfigurationManager.ConnectionStrings["TabloidConnection"].ConnectionString,
out error);
var rep = System.Web.HttpContext.Current.Response;
rep.Clear();
rep.ClearContent();
rep.BufferOutput = true;
rep.ContentType = "application/json; charset=UTF-8";
//rep.Write("ab");
rep.Write("{d:");
rep.Write(JsonConvert.SerializeObject(new jTableResponse(result), Formatting.None));
rep.Write("}");
rep.Flush();
//rep.SuppressContent = true;
rep.End();
//ct.ApplicationInstance.CompleteRequest();
}
public class jTableResponse
{
private int totalRecordCount=0;
private DataTable records;
private string result = "OK";
public string Result
{
get { return result; }
set { result = value; }
}
public int TotalRecordCount
{
get { return totalRecordCount; }
set { totalRecordCount = value; }
}
public DataTable Records
{
get { return records; }
set { records = value; }
}
public jTableResponse(DataTable r)
{
Records = r;
totalRecordCount = r.Rows.Count;
}
}
But i have character added behind and after my json like this (using fiddler)
1d0
{d:{"Result":"OK","TotalRecordCount":10,"Records":[{"id_individu":1,"nom_indiv":"..."},{"id_individu":2,"nom_indiv":"RIVET"},{"id_individu":3,"nom_indiv":"COHEN"},{"id_individu":4,"nom_indiv":"VILLEROUGE"},{"id_individu":5,"nom_indiv":"CAILLARD"},{"id_individu":6,"nom_indiv":"DE CHEVRON VILLETTE"},{"id_individu":7,"nom_indiv":"ROYO"},{"id_individu":8,"nom_indiv":"ROQUES"},{"id_individu":9,"nom_indiv":"GUILLOT"},{"id_individu":10,"nom_indiv":"DORNE-CORRAZE"}]}}
0
Thanks for your response
When i change this
rep.Write("{d:");
rep.Write(JsonConvert.SerializeObject(new jTableResponse(result), Formatting.None));
rep.Write("}");
by this
rep.Write(JsonConvert.SerializeObject(new jTableResponse(result), Formatting.None));
it work fine thanks.
I have serialized my mvc form and now wants to deserialize it in c#.Please help me to tackle this issue.Following is my code of frontend
<input type="search" id="txtsearch">
<input type="button" id="btnsearch" />
<script type="text/javascript">
$(function () {
DrawTable(0);
$('#btnsearch').click(function (e) {
var searchname = $('#txtsearch').val();
var form = $('form').serialize();
//var form = $(this).serializeArray();
DrawTable(form);
});
</script>
and following is the method where i want to get values from serialized data by deserializing
public JsonResult GetAllCustomers(string sEcho, string sColumns, int iDisplayStart, int iDisplayLength, string sSearch, int iSortCol_0, string sSortDir_0, string filters, int UserId = 0,string form="") {
string sortDirection = sSortDir_0;
DataTableGridModel resultModel = new Logic(x,y ).GetCustomersForGrid(sEcho, sColumns, iDisplayStart, iDisplayLength, sSearch, iSortCol_0, sSortDir_0, UserId);
return Json(resultModel, JsonRequestBehavior.AllowGet);
}
Use Newtonsoft.Json.dll for serialization and deserialization of json data in C#
Create below methods using Newtonsoft.Json.dll and invoke deserialize method by passing json data in string format.
private static JsonSerializerSettings CreateSettings()
{
var settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
settings.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
return settings;
}
private static Newtonsoft.Json.JsonSerializer CreateSerializer()
{
var settings = CreateSettings();
return Newtonsoft.Json.JsonSerializer.Create(settings);
}
public T Deserialize<T>(object target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
var result = default(T);
var json = target as string;
if (json != null)
{
var serializer = CreateSerializer();
using (var stringReader = new StringReader(json))
{
using (JsonReader jsonReader = new JsonTextReader(stringReader))
{
result = serializer.Deserialize<T>(jsonReader);
}
}
}
return result;
}
1).ENCODE FORM AS JSON STRING ON CLIENT
//in javascript, serialize the form to JSON:
// -- this will only work if all elements on the form have a name attribute -
var stringToReturnToServer = JSON.stringify($('form').serializeArray());
2). DECODE JSON STRING TO DICTIONARY, SO YOU CAN RETRIEVE ELEMENT BY NAME
Server-side, you'll be dealing with a string containing JSON array of objects that each have two properties, name and value. This translates nicely to a C# Dictionary<string,string>
using Newtonsoft.Json;
private class FormField
{
[JsonProperty("name")]
public string a { get; set; }
[JsonProperty("value")]
public string b { get; set; }
}
private void ReadFormData(string sFormData)
{
//this will throw if you give two form fields the same name in your HTML.
Dictionary<string,string> asFormData = JsonConvert.DeserializeObject<List<FormField>>(sFormData).ToDictionary(x => x.a, x => x.b);
//VALUES OF FORM ELEMENTS NOW ACCESSIBLE BY NAME IN DICTIONARY
string sSearchText = asFormData["txtsearch"];
}
...the code here is limited to serialzing and deserializing, you'll need to GET or POST the actual JSON string back to the server.
[DataContract]
public abstract class BusMessage
{
[DataMember(Name = "encoding")]
public string Encoding { get; set; }
[DataMember(Name = "type")]
public virtual MessageType Type
{
get { return _type; }
private set { _type = value; }
}
}
[DataContract]
public class BusTextMessage : BusMessage
{
[DataMember(Name = "type")]
public override MessageType Type
{
get { return MessageType.Text; }
}
[DataMember(Name = "payload")]
public string Payload { get; set; }
}
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(Helper))]
public interface ICommunicationService
{
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/SendMessage")]
string SendMessage(BusMessage jsonMessage);
}
}
When I send request with Postman chrome, if I don't add __type as "__type":"BusTextMessage:#TransportModels.Messages" the object won't be serialized properly because it doesn't know how to instantiate BusMessage class. I have already defined Type property which defines the type of message. Is there any possibility to override __type behaviour for example return proper implementation depending on Type property? I don't want anyone to put __type information to json manually so is there an option to edit json before deserialization and add __type property manually to json if it doesn't exist? For example I want to do something like this:
public void BeforeDeserialization(string json)
{
if(json doesnt include __type)
{
if(json property type(my property) is MessageType.Text)
add to json "__type":"BusTextMessage:#TransportModels.Messages"
///etc
}
}
I Found this methods but it doesn't seem to be usable:
[OnDeserializing()]
internal void OnDeserializingMethod(StreamingContext context)
{
}
I think you need to add the KnownType attribute to the BusMessage class.
[DataContract]
[KnownType(typeof(BusTextMessage)]
public class BusMessage
{
.
.
.
}
This is the quickest solution I discovered. I configure MessageInspector and handle AfterReceiveRequest. Then I check message format(XML,JSON). If it is XML(for example sent from any WCF Client written in C#, WCF is configured to send everything with XML's) then I accept that message because field __type will be automatically inserted by WCF mechanism. Otherwise I Check if it is JSON, for example sent from external client. If it doesn't contain property "__type" I check my property Type and generate proper __type value. For example if my Type is equal to Text I add __type property BusTextMessage:#TransportModels.Messages and insert it into JSON and then recreate the message. I couldn't find quicker and easier solution and it seems to be working. Handling AfterReceiveRequest I found at http://code.msdn.microsoft.com/windowsdesktop/WCF-REST-Message-Inspector-c4b6790b.
public class MessageTypeInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
RecreateMessage(ref request);
return null;
}
}
private void RecreateMessage(ref Message message)
{
WebContentFormat messageFormat = this.GetMessageContentFormat(message);
var ms = new MemoryStream();
XmlDictionaryWriter writer = null;
switch (messageFormat)
{
case WebContentFormat.Default:
case WebContentFormat.Xml:
writer = XmlDictionaryWriter.CreateTextWriter(ms);
break;
case WebContentFormat.Json:
writer = JsonReaderWriterFactory.CreateJsonWriter(ms);
break;
case WebContentFormat.Raw:
this.ReadRawBody(ref message);
break;
}
message.WriteMessage(writer);
writer.Flush();
string messageBody = Encoding.UTF8.GetString(ms.ToArray());
if (messageFormat == WebContentFormat.Json && !messageBody.Contains("__type"))
messageBody = AddTypeField(messageBody);
ms.Position = 0;
ms = new MemoryStream(Encoding.UTF8.GetBytes(messageBody));
XmlDictionaryReader reader = messageFormat == WebContentFormat.Json ?
JsonReaderWriterFactory.CreateJsonReader(ms, XmlDictionaryReaderQuotas.Max) :
XmlDictionaryReader.CreateTextReader(ms, XmlDictionaryReaderQuotas.Max);
Message newMessage = Message.CreateMessage(reader, int.MaxValue, message.Version);
newMessage.Properties.CopyProperties(message.Properties);
message = newMessage;
}
private WebContentFormat GetMessageContentFormat(Message message)
{
WebContentFormat format = WebContentFormat.Default;
if (message.Properties.ContainsKey(WebBodyFormatMessageProperty.Name))
{
WebBodyFormatMessageProperty bodyFormat;
bodyFormat = (WebBodyFormatMessageProperty)message.Properties[WebBodyFormatMessageProperty.Name];
format = bodyFormat.Format;
}
return format;
}
private string AddTypeField(string jsonReply)
{
var typeRegex = new Regex("\"type\":(?<number>[0-9]*)");
Match match = typeRegex.Match(jsonReply);
if (match.Success)
{
int number = Int32.Parse(match.Groups["number"].Value);
var type = (MessageType)number;
var nameFormat = string.Format("Bus{0}Message", type);
string format = string.Format("\"__type\":\"{0}:#TransportModels.Messages\"", nameFormat);
jsonReply = "{" + string.Format("{0},{1}", format, jsonReply.Substring(1));
return jsonReply;
}
else
{
throw new Exception("Wrong message type.");
}
}
Using our own hardware, we've installed vanilla openstack with all components however I am having problems accessing services other than the Identity due to a region issue. The code used is as follows called with the admin account and admin tennant we created...
public static void TestAccess(string userName, string password, string projectName, string projectId)
{
try
{
Uri baseUrl = new Uri(URL_IDENTITY);
CloudIdentityWithProject projectCloudId = new CloudIdentityWithProject();
projectCloudId.Username = userName;
projectCloudId.Password = password;
projectCloudId.ProjectName = projectName;
projectCloudId.ProjectId = new ProjectId(projectId);
OpenStackIdentityProvider idProvider = new OpenStackIdentityProvider(baseUrl, projectCloudId);
UserAccess userAccess = idProvider.Authenticate(projectCloudId);
IEnumerable<ExtendedEndpoint> eps = idProvider.ListEndpoints(userAccess.Token.Id);
string reg = idProvider.DefaultRegion; // This is null
ServiceCatalog[] scs = userAccess.ServiceCatalog;
// Get the list of regions
regionList = new List<string>();
foreach (ServiceCatalog sc in scs)
{
foreach (Endpoint ep in sc.Endpoints)
{
regionList.Add(ep.Region); // This is 'regionOne' in every case
}
}
// Try stuff...
foreach(string region in regionList.Distinct())
{
// Get a list of containers
CloudFilesProvider cfp = new CloudFilesProvider(projectCloudId, idProvider);
// THIS LINE FAILS
IEnumerable<Container> listOfContainers = cfp.ListContainers(region: region);
foreach (Container ctnr in listOfContainers)
{
Console.WriteLine("Container: {0}", ctnr.Name);
}
CloudNetworksProvider cnp = new CloudNetworksProvider(identity: null, identityProvider: idProvider);
IEnumerable<CloudNetwork> networks = cnp.ListNetworks(identity: null, region: region);
foreach (CloudNetwork network in networks)
{
Console.WriteLine("Network[{0}] name: {1}", networkCount, network.Label);
Console.WriteLine("Network[{0}] Id: {1}", networkCount, network.Id);
++networkCount;
}
Console.WriteLine("{0} networks listed.", networkCount);
}
}
catch(Exception ex)
{
throw;
}
}
The code fails at the call to ListContainers(region: region) with the error... 'The user does not have access to the requested service or region' where as if I don't specify a region the error is simply 'No region was provided, the service does not provide a region-independent endpoint, and there is no default region set for the user's account'
We are only accessing our internal network at the moment so regions aren't important to us yet...
Also of note is that when making a call to...
CloudNetwork detail = cnp.ShowNetwork(networkGuid, "regionOne");
of a network I can see returns the error 'The item was not found or does not exist.'
Help and advice much appreciated.
I managed to extend the functionality of the Openstack.Net SDK fairly simply. The code below extends it to include various functions for Tenant/Project manipulations...
Firstly, create a NewTenant container that will be used to pass data to and from the webservices, I've put it in the same namespace as the others...
using Newtonsoft.Json;
namespace net.openstack.Core.Domain
{
[JsonObject(MemberSerialization.OptIn)]
public class NewTenant
{
/// <summary>
/// Gets the ID for the new user.
/// <note type="warning">The value of this property is not defined. Do not use.</note>
/// </summary>
[JsonProperty("id", DefaultValueHandling = DefaultValueHandling.Include)]
public string Id { get; private set; }
[JsonProperty("name")]
public string Name { get; private set; }
[JsonProperty("description")]
public string Description { get; private set; }
[JsonProperty("enabled")]
public bool Enabled { get; private set; }
public NewTenant(string name, string description, bool enabled = true)
{
Name = name;
Description = description;
Enabled = enabled;
}
}
}
Now we can create any new Request classes for posting the data...
using System;
using Newtonsoft.Json;
using net.openstack.Core.Domain;
namespace net.openstack.Core.Request
{
[JsonObject(MemberSerialization.OptIn)]
internal class AddTenantRequest
{
[JsonProperty("tenant")]
public NewTenant Tenant { get; private set; }
public AddTenantRequest(NewTenant tenant)
{
if (tenant == null)
throw new ArgumentNullException("tenant");
Tenant = tenant;
}
}
}
Now create the Response objects for the requests to help retrieve the data
using net.openstack.Core.Domain;
using Newtonsoft.Json;
namespace net.openstack.Core.Response
{
[JsonObject(MemberSerialization.OptIn)]
internal class NewTenantResponse
{
[JsonProperty("tenant")]
public NewTenant NewTenant { get; private set; }
}
[JsonObject(MemberSerialization.OptIn)]
internal class TenantResponse
{
[JsonProperty("tenant")]
public Tenant Tenant { get; private set; }
}
}
Now we can create a class that inherits from OpenStackIdentityProvider with the additional functionality for Tenant/Project manipulation that we want...
using System;
using System.Net;
using JSIStudios.SimpleRESTServices.Client;
using net.openstack.Core.Domain;
using net.openstack.Core.Request;
using net.openstack.Core.Response;
namespace net.openstack.Core.Providers
{
public class ExtendedOpenStackIdentityProvider : OpenStackIdentityProvider
{
public ExtendedOpenStackIdentityProvider(Uri urlBase)
: base(urlBase)
{
}
public ExtendedOpenStackIdentityProvider(Uri urlBase, CloudIdentity identity)
: base(urlBase, identity)
{
}
public ExtendedOpenStackIdentityProvider(Uri urlBase, JSIStudios.SimpleRESTServices.Client.IRestService restService, net.openstack.Core.Caching.ICache<UserAccess> tokenCache)
: base(urlBase, restService, tokenCache)
{
}
public ExtendedOpenStackIdentityProvider(Uri urlBase, CloudIdentity identity, JSIStudios.SimpleRESTServices.Client.IRestService restService, net.openstack.Core.Caching.ICache<UserAccess> tokenCache)
: base(urlBase, identity, restService, tokenCache)
{
}
public NewTenant AddTenant(NewTenant tenant, CloudIdentity identity)
{
if (tenant == null)
throw new ArgumentNullException("tenant");
if (string.IsNullOrEmpty(tenant.Name))
throw new ArgumentException("tenant.Name cannot be null or empty");
if (tenant.Id != null)
throw new InvalidOperationException("tenant.Id must be null");
CheckIdentity(identity);
var response = ExecuteRESTRequest<NewTenantResponse>(identity, new Uri(UrlBase, "/v2.0/tenants"), HttpMethod.POST, new AddTenantRequest(tenant));
if (response == null || response.Data == null)
return null;
return response.Data.NewTenant;
}
public Tenant GetTenant(string tenantId, CloudIdentity identity)
{
if (tenantId == null)
throw new ArgumentNullException("tenantId");
CheckIdentity(identity);
var urlPath = string.Format("v2.0/tenants/{0}", tenantId);
var response = ExecuteRESTRequest<TenantResponse>(identity, new Uri(UrlBase, urlPath), HttpMethod.GET);
if (response == null || response.Data == null)
return null;
return response.Data.Tenant;
}
public bool DeleteTenant(string tenantId, CloudIdentity identity)
{
if (tenantId == null)
throw new ArgumentNullException("tenantId");
if (string.IsNullOrEmpty(tenantId))
throw new ArgumentException("tenantId cannot be empty");
CheckIdentity(identity);
var urlPath = string.Format("v2.0/tenants/{0}", tenantId);
var response = ExecuteRESTRequest(identity, new Uri(UrlBase, urlPath), HttpMethod.DELETE);
if (response != null && response.StatusCode == HttpStatusCode.NoContent)
return true;
return false;
}
public bool AddTenantUserRole(string tenantId, string userId, string roleId, CloudIdentity identity)
{
if (tenantId == null)
throw new ArgumentNullException("tenantId");
if (string.IsNullOrEmpty(tenantId))
throw new ArgumentException("tenantId cannot be empty");
if (userId == null)
throw new ArgumentNullException("userId");
if (string.IsNullOrEmpty(userId))
throw new ArgumentException("userId cannot be empty");
if (roleId == null)
throw new ArgumentNullException("roleId");
if (string.IsNullOrEmpty(roleId))
throw new ArgumentException("roleId cannot be empty");
CheckIdentity(identity);
var urlPath = string.Format("v2.0/tenants/{0}/users/{1}/roles/OS-KSADM/{2}", tenantId, userId, roleId);
var response = ExecuteRESTRequest(identity, new Uri(UrlBase, urlPath), HttpMethod.PUT);
if (response != null && response.StatusCode == HttpStatusCode.NoContent)
return true;
return false;
}
}
}
I imagine that this functionality will appear in the GitHub version soon, but if not I hope it's useful.