|
I have an OData api and I wanna have a client side software to send request to this api and recieve answer. I used simple odata client but it gives me the answer in dictionary. I need the answer in object. Some people told me to use microsoft-odata-client and I search for it and I cannot fined any good answer for my problem. Anybody can help me?
|
|
|
|
|
According to the documentation, you should be able to feed the API a JSON string and receive one back. The JSON returned should be able to be cast to your model being Linq capable.
Actions and Functions in OData v4 Using ASP.NET Web API 2.2 | Microsoft Docs
Here is a sample Http Response header in the documentation. The returned data is in JSON format.
HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true
OData-Version: 4.0
Date: Sat, 28 Jun 2014 00:44:07 GMT
Content-Length: 85
{
"@odata.context":"http://localhost:38479/$metadata#Edm.Decimal","value":50.00
}
This is simple JSON. It may look like a dictionary but it's not. It's similar to YAML as well.
"@odata.context":"http://localhost:38479/$metadata#Edm.Decimal",
"value":50.00
You can test with Postman; send a request and inspect the response in raw format to confirm if it's your code or the API result.
The Basics of Using Postman for API Testing - YouTube
But I think your just mistaking this for Dictionary, because I can't see a dictionary as being capable of HTTP transport.
Now you need to make a model of the result to convert the JSON result. or use var result = callapi();
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Hi
I have an existing class that sits in a library project that is used natively for handling data object instances and also serialized/deserialized for use with json, xml and datasets. Changing the class looks to be tricky without compromising other projects.
I'm trying to put a SOAP wrapper around some of the class logic but running into problems because the class has multiple Subclasses with the same name.
Error
Types 'Library.DataModel.HardwareOrder.ResponseSet' and 'Library.DataModel.ProduceOrder.ResponseSet' both use the XML type name, 'ResponseSet', from namespace 'http://MyTest.com/'. Use XML attributes to specify a unique XML name and/or namespace for the type.
This is my ASMX
<WebMethod()>
Public Function SubmitHardwareOrder(ByVal Parameters As DataModel.HardwareOrder.Parameters) As DataModel.HardwareOrder.ResponseSet
End Function
<WebMethod()>
Public Function SubmitProduceOrder(ByVal Parameters As DataModel.ProduceOrder.Parameters) As DataModel.ProduceOrder.ResponseSet
End Function
This is a small sample of my class
Public Class DataModel
Public Class HardwareOrder
Public Class ResponseSet
Public Property ResponseHeader As List(Of ResponseHeaderRow)
Public Class ResponseHeaderRow
Public Property TransactSucceed As Boolean
Public Property TransactCode As String
Public Property TransactDescription As String
Public Property TransactionReference As String
Public Property TpxID As String
End Class
End Class
End Class
Public Class ProduceOrder
Public Class ResponseSet
Public Property ResponseHeader As List(Of ResponseHeaderRow)
Public Class ResponseHeaderRow
Public Property TransactSucceed As Boolean
Public Property TransactCode As String
Public Property TransactDescription As String
Public Property StaffID As String
Public Property PurchaseOrder As String
End Class
End Class
End Class
End Class
I've been looking for solutions but so far I haven't found anything that has enabled me to use my existing class without alteration.
Does anyone know of any tricks that can be done in the ASMX to make it work?
modified 26-Apr-19 23:38pm.
|
|
|
|
|
I was going to answer this a couple of days ago when I was compiling; sorry about that. Had to test it.
You really just have a bad design and should change it. If your using this for soap you should decorate the class with serializable, so the data sent back to the client can be encoded.
I would of wrote it like this to make ResponseSet reusable.
Public Class DataModel
[Serializable()]
Public Class HardwareOrder
Public Class ResponseSet
Public Property TpxID As String
Public Property ResponseHeader As List(Of ResponseHeaderRow)
End Class
End Class
[Serializable()]
Public Class ProduceOrder
Public Class ResponseSet
Public Property StaffID As String
Public Property ResponseHeader As List(Of ResponseHeaderRow)
End Class
End Class
[Serializable()]
Public Class ResponseHeaderRow
Public Property TransactSucceed As Boolean
Public Property TransactCode As String
Public Property TransactDescription As String
Public Property TransactionReference As String
End Class
End Class
Or perhaps add a property to the ResponseHeader called ID, a generic name and drop your property of TpxId. But if you do that then there is no need to have HardwareOrder and ProduceOrder because they become the same model. Technically this can just become
[Serializable()]
Public Class Order
Public Property Id As String
Public Property TransactSucceed As Boolean
Public Property TransactCode As String
Public Property TransactDescription As String
Public Property TransactionReference As String
End Class
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Hi Jkirkerx
Thanks for your posting. I tried it the code compiles fine but the same error I described earlier arises from the asmx at runtime
Error
Types 'Library.DataModel.HardwareOrder.ResponseSet' and 'Library.DataModel.ProduceOrder.ResponseSet' both use the XML type name, 'ResponseSet', from namespace 'http://MyTest.com/'. Use XML attributes to specify a unique XML name and/or namespace for the type.
When serializing to xml or json the class works fine but in SOAP things start to get a little ugly.
I found a solution that makes it work by adding the following XmlElement tags to the routines.
<WebMethod()>
Public Function SubmitHardwareOrder(<XmlElement("Parameters", Namespace:="http://MyTest.com/HardwareOrder.Parameters")> Parameters As DataModel.HardwareOrder.Parameters) As XmlElement("ResponseSet", Namespace:="http://MyTest.com/HardwareOrder.ResponseSet")> DataModel.HardwareOrder.ResponseSet
End Function
<WebMethod()>
Public Function SubmitProduceOrder(<XmlElement("Parameters", Namespace:="http://MyTest.com/ProduceOrder.Parameters")> Parameters As DataModel.ProduceOrder.Parameters) As XmlElement("ResponseSet", Namespace:="http://MyTest.com/ProduceOrder.ResponseSet")> DataModel.ProduceOrder.ResponseSet
End Function
I note that yes the above makes it work but its not beautiful because when you generate your web reference in visual studio the generated class does not have levels eg not not do this "DataModel.ProduceOrder.ResponseSet" instead its just "ResponseSet" and so next time it sees another class called "ResponseSet" it renames it to "ResponseSet1" and next time "ResponseSet2" and so on. So if you are working of a large complicated namespace/class with many levels the web references created wont be overly intuitive if naming is not unique.
Clearly SOAP (Simple Object Access Protocol) is just that simple and this endeavor hits it's limitations bang on.
The foreseeable options are
-consume the webservice as per my above example with the inconvenience of none intuitive naming
-modify the class or create a separate duplicated class just for SOAP webservice
-use SOAP differently with passing/returning literals/datasets not strictly working of object model
-modify or build the wsdl class manually (this is the biggest time waster! I stay well away from wsdls that dont work as is especially if not generated by visual studio)
-just use xml or json and stream the data back via a handler
-use something else WCF?
|
|
|
|
|
I don't know. It looks like your still using the original models or classes to me and not the modified ones.
I wrote mine like this, but used serialized classes and not actual XML
Then tested it calling the API in the browser, and getting that white and blue page that shows the all the WSDL services.
I remember seeing my class outputted on the screen, but can't remember if it was XML. But I wrote a Win App to call this web service and it worked really well.
<WebMethod(EnableSession:=True)>
Public Function customers_load(
ByVal CustomerRequest As ws_customers_Request) As ws_customers_Response
Dim customer As New ws_customers_Response
Dim customerList As List(Of ws_customers_list) = Nothing
Dim dwXCode As Integer = crm_ef_login.administrator_Login(
CustomerRequest.Credentials_Key,
CustomerRequest.Credentials_Password
)
If (0 = dwXCode) Then
If CustomerRequest.PageIndex = 0 Then CustomerRequest.PageIndex = 1
If CustomerRequest.PageSize = 0 Then CustomerRequest.PageSize = 25
Dim m_count As Integer = crm_ws_ef_customers.customers_Load(
CustomerRequest.PageIndex,
CustomerRequest.PageSize,
customerList
)
If (m_count > 0) Then
customer.response_Code = "OK"
customer.response_Text = m_count & " subscribers have loaded successfully"
customer.customerList = customerList
Else
customer.response_Code = "E001"
customer.response_Text = "No subscribers exist in the database"
customer.customerList = customerList
End If
Else
customer.response_Code = "E000"
customer.response_Text = "Failed Authentication"
customer.customerList = Nothing
End If
Return customer
End Function
<Serializable()>
Public Class ws_customers_Response
Private m_response_Code As String
Private m_response_Text As String
Private m_customerList As List(Of ws_customers_list)
Public Property response_Code As String
Get
Return m_response_Code
End Get
Set(value As String)
m_response_Code = value
End Set
End Property
Public Property response_Text As String
Get
Return m_response_Text
End Get
Set(value As String)
m_response_Text = value
End Set
End Property
Public Property customerList As List(Of ws_customers_list)
Get
Return m_customerList
End Get
Set(value As List(Of ws_customers_list))
m_customerList = value
End Set
End Property
End Class
<Serializable()>
Public Class ws_customers_list
Private m_CustomerID As Integer
Private m_FirstName As String
Private m_LastName As String
Private m_EmailAddress As String
Public Property CustomerID As Integer
Get
Return m_CustomerID
End Get
Set(value As Integer)
m_CustomerID = value
End Set
End Property
Public Property FirstName As String
Get
Return m_FirstName
End Get
Set(value As String)
m_FirstName = value
End Set
End Property
Public Property LastName As String
Get
Return m_LastName
End Get
Set(value As String)
m_LastName = value
End Set
End Property
Public Property EmailAddress As String
Get
Return m_EmailAddress
End Get
Set(value As String)
m_EmailAddress = value
End Set
End Property
End Class
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Hi,
Want to develop a software by which view and print the sql data by searching data by specific name , date and time. Can anyone guide me ?
|
|
|
|
|
|
Hello,
I am trying to share a few API's between multiple sites on the same server (IIS 8.5).
In a simple architecture, I would have each site on its own port, and each API on its own port, with the sites pointing to the API's they need.
Unfortunately, we have a restriction that forces us to have the actual API's "under" the main site, by using "add application" in IIS, and using aliases for each API.
This works fine actually.
What I would like to now is to have other sites use the same API's, also by having aliases, but without physically duplicating the API's either on disk, or even in memory.
Put simply, it looks like this:
localhost:1000/index.html = site1
localhost:1000/aliasAPI1/… = api1
localhost:1000/aliasAPI2/… = api2
…
and I would like:
localhost:2000/index.html = site2
localhost:2000/aliasAPI1/… = api1 = same as on site 1, in the same physical folder
localhost:2000/aliasAPI2/… = api2 = same as on site 1, in the same physical folder
The reason being that site 1 is fully intranet, and site 2 will be visible from the outside world via junctions created somewhere else on the network, and where we want to enable only 1 port to reach site 2.
I actually made a test simply by adding applications under site 2, and pointing physically to the same API folders, and it works, but it shows that the API's are ran twice in memory.
Tried both in the same application pool, and in separate pools.
Is there a way to really share the API's in a configuration like this one ?
I've Googled the issue.. but couldn't find anything relevant
Any help would be appreciated
Fred
|
|
|
|
|
|
Oh I did not know ARR .. I will look into it deeper, but at first glance it looks like it could solve my problem. Many thanks !
|
|
|
|
|
Wow what a trip! Sort of excited that I finally got my app to work in a production environment.
Having to learn Docker like real fast, and then really having to understand how .Net Core 2.2 works. What made it worst was wrapping Angular V7 in .Net Core 2.2, making it much more complicated now. And then connecting it to MongoDB running in another container.
Working with VS2017 and Docker
VS2017 gives you the ability to run your .Net Core 2.2 app in a Docker for Windows container so you can test and debug. But after creating the container, you can't start it again unless you use VS2017 to run it again. What ends up happening is that VS2017 does 1/2 the work in the background and uses the needed components from your shared drive and you can't see it unless you look really close at the output. Now try and use release to build that app and put it in a container, still won't work because your missing the rest of the files needed to run it that are on your shared drive. When you go to peek inside a debug container, it's totally different than a release container. You have to alter your Dockerfile to copy the rest of the files needed to run isolated without a shared drive. Then when you push to Docker Hub you will have everything required.
Visual Studio 2017 will program your environment variables, but to run self contained you have to create them in your Dockerfile or docker-compose.yaml file. eg. DOTNET_RUNNING_IN_CONTAINER=true
VS2017 and Azure:
I actually got to the point where I thought that Docker support for VS2017 was locked into Azure, and that they didn't want us to host Docker containers ourselves, but that was not the case. What it boiled down to was going back to basics and building my project by command line to better understand how "dotnet" works and then build the Docker container. Once I understood the relationship between the two, I was able to go back to VS2017 and craft a better Dockerfile, and then compose it. But what works in Docker for Windows is a whole different story in Docker for Linux.
So to answer some questions that you may have:
Can you host your .Net Core 2.2 app in Docker just using Kestrel - YES
Can you program Kestrel to use SSL with an embedded PFX file - YES
Can you control Kestrel's ciphers such as TLS, no SSL - YES
Do you need a reverse proxy server such as Nginx - NO - so far I haven't had to
Will the stock Dockerfile work - NO - You have to modify it to your needs
Do the current MongoDB C# V2.8 drivers work with Docker and .Net Core 2.2 - YES - but programing the connection string is different than not being in a container. SHA256 auth errors.
Some Advice:
Learn "dotnet" command line first before learning Docker.
Carefully prepare your Programs.cs file for Docker, because if this file crashes your container startup, you won't be able to debug it. No logs, nothing. Add Logging to your Programs.cs will help isolate issues.
Don't hard code much, use json files instead.
Don't trust search engine results:
The most frustrating part is the ocean of outdated information on the internet. When I started learning Angular, all the information was outdated and for V2 and not V6. But it's been cleaned up now. It's the same for .Net Core 2.2 and Docker in which the info is outdated.
Port Numbers:
The other frustrating issue is port numbers. Why does .Net Core want to use ports like 5000, 5001?
When you develop for IIS, normally the port number is 44367 or something. I still don't have the answer for this but used ports 80,443 any ipAddress in Programs.cs and set the ip address in Docker. This took the longest to understand.
Version of Linux:
I tried 2 versions, CentOs and Ubuntu. Not being a fan of Ubuntu, I used it because of it's small footprint and builtin Docker, Docker-Compose support. The build size is so small, I think I can run this on a Raspberry. So Ubuntu Bionic Beaver V18 worked the best.
So what's next?
I'll cleanup my website content at home and run the Docker Compose production version for a couple of weeks. Then build the next server with Docker Swarm and see how that works.
Hope this helps someone looking to do the same thing.
March 16, 2019
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
That is a good candidate for a Tip, or with a little more detail, as an Article.
|
|
|
|
|
Good idea!
But I need to get more knowledgeable about it first. A couple of things back fired on me as I tried to perfect Kestrel to obtain a "A" rating on GMetrix, but I figured it out. As I perfected external HTTP request, I broke the internal HTTP request.
And I still have to fix the problem with using the refresh button on the browser which is an Angular or SPA issue not playing nice with .Net Core's routing. I see Microsoft has created a new project template for React/Angular/SPA that seems to have fixed it; and it uses a more native version of Angular for wrapping without using Web Pack. This I'm happy to see because it makes more sense to be able to just create an Angular project and then wrap it in .Net Core.
But overall, just getting .Net Core 2.2.4 working in Docker for production use using SSL would be a good place to start.
Maybe later this month. The link below is a working example of the project running in Docker using just Kestrel. It's a work in progress, the refresh button may not work, and I'm trying to determine the best way to fix it.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Actually in my GirdView link button click open new page with passing more than one values usin querystring. Now we want to remove querystring. And we don't want to use session. is their any process to pass values.
Thanks
|
|
|
|
|
|
Hi,
Question, I was trying to get expiry date from my database, I already got those list display on my Listview.
But when Im trying to update the year. Still showing on my list.
sample Date today is 13-Apr-2019, i want to display those upcoming expiry +30 Days.
but if I update it to 13-Apr-2020, still showing.
My code i use.
"Select * from TblEmployee where IDExpiry<=@IDExpiry"
siemdi.Parameters.Add("@IDExpiry", OleDbType.Date).Value = DateTime.Today.AddDays(30)
|
|
|
|
|
Your question is not much clear but your query will return you data for whatever date you pass as parameter and if Tblemployee has the data. if you just want to get expiry data for next 30 days you should have logic not to pass future date.
modified 20-Sep-20 21:01pm.
|
|
|
|
|
That doesn't make much sense to me. If the expiry date is on or before today, then it's also on or before 30 days in the future. Or a year in the future.
What are you actually trying to return?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
You should return a model when you read the database.
A model is a strong typed class that you use to store data in.
Once you have the model populated, you can add 30 days to the date column by using .AddDays(30) in a loop.
So matter what month it is, it will calculate the proper date.
Eg Model:
public class Example {
public string Name { get; set; }
public DateTime Expires { get; set; }
}
Request data and populate the model
var examples = getExamples();
for each example in examples {
example.Expires.AddDays(30);
}
If your not using models, then you be able to figure this out somehow. You just need a DateTime Object and AddDays(30)
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Hi Friends,
Can anyone help me with this?
Using 3 tier architecture,how to fetch data directly from database table to textboxes when I clicked on select button in grid view,I have a table in SQL database.Upon clicking on select link button in grid view,the selected row values must be fetched from database table to text boxes and must be filled with respective values according to database table.I have used sqldatareader, taken OnSelectedIndexChanged ,written query in stored procedure for fetching selected row but values are not binding to text boxes.Any suggestions would be helpful.
|
|
|
|
|
As you did not showed what you have tried it will be hard us to know. Did you tried to debug and see if you really pulling any values back on your event to bind?
modified 20-Sep-20 21:01pm.
|
|
|
|
|
DAL:
public DataTable FetchDetails(string pid, string pname, string pcid, string sdesc, string desc, string qty, string prce, string len)
{
var a = new ArrayList();
SqlCommand cmd = new SqlCommand("spfetchdetail", con);
con.Open();
cmd.ExecuteNonQuery();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@pid", pid);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
pid = sdr["P_id"].ToString();
pname = sdr["P_name"].ToString();
pcid = sdr["c_name"].ToString();
sdesc = sdr["P_shortdesc"].ToString();
desc = sdr["P_desc"].ToString();
qty = sdr["P_qty"].ToString();
prce = sdr["P_price"].ToString();
len = sdr["P_length"].ToString();
a.Add(pid); a.Add(pname); a.Add(pcid); a.Add(sdesc); a.Add(desc); a.Add(qty); a.Add(prce); a.Add(len);
}
return dt;
}
BAL:
public object fetchdetail(string pid, string pname, string pcid, string sdesc, string desc, string qty, string prce, string len)
{
return dll.FetchDetails(pid, pname, pcid, sdesc, desc, qty, prce, len);
}
CS:
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
string pid = ""; string pname = ""; string pcid = ""; string sdesc = ""; string desc = ""; string qty = ""; string prce = ""; string len = "";
bll.fetchdetail(pid, pname, pcid, sdesc, desc, qty, prce, len);
HiddenField1.Value = pid;
txt_proName.Text = pname;
ddl_category.SelectedValue = pcid;
txt_sdesc.Text = sdesc;
txt_ldesc.Text = desc;
txt_qnty.Text = qty;
txt_price.Text = prce;
txt_len.Text = len;
}
|
|
|
|
|
Couple of issues with your code in
FetchDetails method.
1. You have populated the result into arraylist object which is local to this function
2. You executing command object with ExecuteNonQuery, Reader and DataAdapter
3. You populated Dataset to return from FetchDetails in DAL and did not received it in calling method to bind data.
Populate your local variables in SelectChange event from DataSet object you reveiced from BAL and should work for you.
modified 20-Sep-20 21:01pm.
|
|
|
|
|
Thank u for u r response.
Unfortunately I am new to work with three tier, I am unable to get your point.Could u pls modify the code which i have provided so that it will be very helpful for me.
|
|
|
|
|