How can I change message in DuplexSessionChannel (tcpTransport) in WCF custom channel? - wcf

I implement IDuplexSessionChannel on my Custom Channel because I use tcpTransport. In that custom channel, I cache service call response(client side caching). But it has errors. In IRequestChannel it works fine. How can I change message in TryMessage method. My code :
public Message Receive(TimeSpan timeout)
{
Message response = null;
response = CommunicationCacheManager.Get(_request.Headers.Action, _request);
if (response == null)
{
response = this.InnerChannel.Receive(timeout);
int cacheTimeout = 0;
if (response.Headers.FindHeader(Constants.CacheTimeOutHeader.NAME, Constants.CacheTimeOutHeader.NAMESPACE) > -1)
{
cacheTimeout = response.Headers.GetHeader<int>(Constants.CacheTimeOutHeader.NAME, Constants.CacheTimeOutHeader.NAMESPACE);
}
if (cacheTimeout > 0 && response != null &&
!response.IsFault &&
!response.IsEmpty)
{
CommunicationCacheManager.Add(_request.Headers.Action, cacheTimeout, ref response);
}
}
return response;
}
public Message Receive()
{
return this.InnerChannel.Receive();
}
public bool TryReceive(TimeSpan timeout, out Message message)
{
ThrowIfDisposedOrNotOpen();
message = null;
bool timedout = false;
try
{
message = this.Receive(timeout);
}
catch (TimeoutException)
{
timedout = true;
}
return (!timedout);
}
CacheManager works. And I get the response Cache. But tryReceive run again and when I look Message. Message is closed. How can I fix that

Problem is solved.
Tcp Binding add RelatesTo Header to Message. So code is changed to
public Message Receive(TimeSpan timeout)
{
Message response = null;
response = CommunicationCacheManager.Get(_request.Headers.Action, _request);
if (response == null)
{
response = this.InnerChannel.Receive(timeout);
int cacheTimeout = 0;
if (response.Headers.FindHeader(Constants.CacheTimeOutHeader.NAME, Constants.CacheTimeOutHeader.NAMESPACE) > -1)
{
cacheTimeout = response.Headers.GetHeader<int>(Constants.CacheTimeOutHeader.NAME, Constants.CacheTimeOutHeader.NAMESPACE);
}
if (cacheTimeout > 0 && response != null &&
!response.IsFault &&
!response.IsEmpty)
{
CommunicationCacheManager.Add(_request.Headers.Action, cacheTimeout, ref response);
}
}
else
{
response.Headers.RelatesTo=_request.Header.MessageId;
}
return response;
}

Related

Using MQTT ManagedClient with ASP NET API, how to?

I'm currently working on a project that has to rely heavily on MQTT - one of the parts that needs to utilize MQTT is a ASP Net API, but I'm having difficulties receiving messages.
Here is my MQTTHandler:
public MQTTHandler()
{
_mqttUrl = Properties.Resources.mqttURL ?? "";
_mqttPort = Properties.Resources.mqttPort ?? "";
_mqttUsername = Properties.Resources.mqttUsername ?? "";
_mqttPassword = Properties.Resources.mqttUsername ?? "";
_mqttFactory = new MqttFactory();
_tls = false;
}
public async Task<IManagedMqttClient> ConnectClientAsync()
{
var clientID = Guid.NewGuid().ToString();
var messageBuilder = new MqttClientOptionsBuilder()
.WithClientId(clientID)
.WithCredentials(_mqttUsername, _mqttPassword)
.WithTcpServer(_mqttUrl, Convert.ToInt32(_mqttPort));
var options = _tls ? messageBuilder.WithTls().Build() : messageBuilder.Build();
var managedOptions = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
.WithClientOptions(options)
.Build();
_mqttClient = new MqttFactory().CreateManagedMqttClient();
await _mqttClient.StartAsync(managedOptions);
Console.WriteLine("Klient startet");
return _mqttClient;
}
public async Task PublishAsync(string topic, string payload, bool retainFlag = true, int qos = 1)
{
await _mqttClient.EnqueueAsync(new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(payload)
.WithQualityOfServiceLevel((MQTTnet.Protocol.MqttQualityOfServiceLevel)qos)
.WithRetainFlag(retainFlag)
.Build());
Console.WriteLine("Besked published");
}
public async Task SubscribeAsync(string topic, int qos = 1)
{
var topicFilters = new List<MQTTnet.Packets.MqttTopicFilter>
{
new MqttTopicFilterBuilder()
.WithTopic(topic)
.WithQualityOfServiceLevel((MQTTnet.Protocol.MqttQualityOfServiceLevel)(qos))
.Build()
};
await _mqttClient.SubscribeAsync(topicFilters);
}
public Status GetSystemStatus(MqttApplicationMessageReceivedEventArgs e)
{
try
{
var json = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
var status = JsonSerializer.Deserialize<Status>(json);
if (status != null)
{
return status;
}
else
{
return null;
}
}
catch (Exception)
{
throw;
}
}
The above has been tested with a console app and works as it should.
The reason I need MQTT in the APi is that a POST method has to act on the value of a topic;
In particular I need to check a systems status before allowing the post;
[HttpPost]
public async Task<ActionResult<Order>> PostOrder(Order order)
{
if (_lastStatus != null)
{
if (_lastStatus.OpStatus)
{
return StatusCode(400, "System is busy!");
}
else
{
var response = await _orderManager.AddOrder(order);
return StatusCode(response.StatusCode, response.Message);
}
}
return StatusCode(400, "Something went wrong");
}
So I will need to set up a subscriber for this controller, and set the value of _lastStatus on received messages:
private readonly MQTTHandler _mqttHandler;
private IManagedMqttClient _mqttClient;
private Status _lastStatus;
public OrdersController(OrderManager orderManager)
{
_orderManager = orderManager;
_mqttHandler = new MQTTHandler();
_mqttClient = _mqttHandler.ConnectClientAsync().Result;
_mqttHandler.SubscribeAsync("JSON/Status");
_mqttClient.ApplicationMessageReceivedAsync += e =>
{
_lastStatus = _mqttHandler.GetSystemStatus(e);
return Task.CompletedTask;
};
}
However, it's behaving a little odd and I'm not experienced enough to know why.
The first time I make a POST request, _lastStatus is null - every following POST request seem to have the last retained message.
I'm guessing that I am struggling due to stuff being asynchronous, but not sure, and every attempt I've attempted to make it synchronous have failed.
Anyone have a clue about what I'm doing wrong?

org.apache.fop.fo.flow.ExternalGraphic catches and logs ImageException I want to handle myself

I am transforming an Image into pdf for test purposes.
To ensure that the Image is compatible with the printing process later on, I'm running a quick test print during the upload.
I'm creating a simple Test-PDF with a transformer. When I try to print an image with an incompatible format, the ImageManager of the transformer throws an ImageException, starting in the preloadImage() function:
public ImageInfo preloadImage(String uri, Source src)
throws ImageException, IOException {
Iterator iter = registry.getPreloaderIterator();
while (iter.hasNext()) {
ImagePreloader preloader = (ImagePreloader)iter.next();
ImageInfo info = preloader.preloadImage(uri, src, imageContext);
if (info != null) {
return info;
}
}
throw new ImageException("The file format is not supported. No ImagePreloader found for "
+ uri);
}
throwing it to:
public ImageInfo needImageInfo(String uri, ImageSessionContext session, ImageManager manager)
throws ImageException, IOException {
//Fetch unique version of the URI and use it for synchronization so we have some sort of
//"row-level" locking instead of "table-level" locking (to use a database analogy).
//The fine locking strategy is necessary since preloading an image is a potentially long
//operation.
if (isInvalidURI(uri)) {
throw new FileNotFoundException("Image not found: " + uri);
}
String lockURI = uri.intern();
synchronized (lockURI) {
ImageInfo info = getImageInfo(uri);
if (info == null) {
try {
Source src = session.needSource(uri);
if (src == null) {
registerInvalidURI(uri);
throw new FileNotFoundException("Image not found: " + uri);
}
info = manager.preloadImage(uri, src);
session.returnSource(uri, src);
} catch (IOException ioe) {
registerInvalidURI(uri);
throw ioe;
} catch (ImageException e) {
registerInvalidURI(uri);
throw e;
}
putImageInfo(info);
}
return info;
}
}
throwing it to :
public ImageInfo getImageInfo(String uri, ImageSessionContext session)
throws ImageException, IOException {
if (getCache() != null) {
return getCache().needImageInfo(uri, session, this);
} else {
return preloadImage(uri, session);
}
}
Finally it gets caught and logged in the ExternalGraphic.class:
/** {#inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
src = pList.get(PR_SRC).getString();
//Additional processing: obtain the image's intrinsic size and baseline information
url = URISpecification.getURL(src);
FOUserAgent userAgent = getUserAgent();
ImageManager manager = userAgent.getFactory().getImageManager();
ImageInfo info = null;
try {
info = manager.getImageInfo(url, userAgent.getImageSessionContext());
} catch (ImageException e) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageError(this, url, e, getLocator());
} catch (FileNotFoundException fnfe) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageNotFound(this, url, fnfe, getLocator());
} catch (IOException ioe) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageIOError(this, url, ioe, getLocator());
}
if (info != null) {
this.intrinsicWidth = info.getSize().getWidthMpt();
this.intrinsicHeight = info.getSize().getHeightMpt();
int baseline = info.getSize().getBaselinePositionFromBottom();
if (baseline != 0) {
this.intrinsicAlignmentAdjust
= FixedLength.getInstance(-baseline);
}
}
}
That way it isn't accessible for me in my code that uses the transformer.
I tried to use a custom ErrorListener, but the transformer only registers fatalErrors to the ErrorListener.
Is there any way to access the Exception and handle it myself without changing the code of the library?
It was easier than I thought. Before I call the transformation I register a costum EventListener to the User Agent of the Fop I'm using. This Listener just stores the Information what kind of Event was triggered, so I can throw an Exception if it's an ImageError.
My Listener:
import org.apache.fop.events.Event;
import org.apache.fop.events.EventListener;
public class ImageErrorListener implements EventListener
{
private String eventKey = "";
private boolean imageError = false;
#Override
public void processEvent(Event event)
{
eventKey = event.getEventKey();
if(eventKey.equals("imageError")) {
imageError = true;
}
}
public String getEventKey()
{
return eventKey;
}
public void setEventKey(String eventKey)
{
this.eventKey = eventKey;
}
public boolean isImageError()
{
return imageError;
}
public void setImageError(boolean imageError)
{
this.imageError = imageError;
}
}
Use of the Listener:
// Start XSLT transformation and FOP processing
ImageErrorListener imageListener = new ImageErrorListener();
fop.getUserAgent().getEventBroadcaster().addEventListener(imageListener);
if (res != null)
{
transformer.transform(xmlDomStreamSource, res);
}
if(imageListener.isImageError()) {
throw new ImageException("");
}
fop is of the type Fop ,xmlDomStreamSource ist the xml-Source I want to transform and res is my SAXResult.

HttpContext.Current is Null visiting website

Im having af Website where im storing a global variable with settings in the HttpContext.Current.Application object
Lately i got some errors because the HttpContext.Current returns null, how can that happen and i there some way to "restart" the application in code
I never get the error on debug/test
The code is :
public static Comito.CMS.Domain.Entity.Solution.Solution GetStoredSolution()
{
try
{
if (HttpContext.Current.Application["Solution"] == null)
{
Comito.CMS.Domain.Entity.Solution.Solution result = Comito.CMS.Helpers.Main.GetStoredSolutionFromConfig();
if (result != null)
{
HttpContext.Current.Application.Lock();
HttpContext.Current.Application["Solution"] = result;
HttpContext.Current.Application.UnLock();
}
else
HttpContext.Current.Response.Redirect("http://www.comito.dk");
return result;
}
object tmpSolution = HttpContext.Current.Application["Solution"];
if (tmpSolution != null)
{
if (tmpSolution.GetType() == typeof(Comito.CMS.Domain.Entity.Solution.Solution))
return (Comito.CMS.Domain.Entity.Solution.Solution)tmpSolution;
}
else
return Comito.CMS.Helpers.Main.GetStoredSolutionFromConfig();
return null;
}
catch (Exception ex)
{
return null;
}
}

Read the Axis2 output from client (Stub)

I am getting value till toEnvelope method. when I try to read from axisclient(WS client)
am getting null value.
System.out.println("toEnvelope :"+param.getOTA_VehCancelRSSequence_type0().getVehCancelRSCore().getUniqueID().getID());
org.apache.axiom.soap.SOAPEnvelope emptyEnvelope = factory.getDefaultEnvelope();
Please help me to over come this
You can get the last OperationContext using the getLastOperationContext() method from the client.
For outgoing messages:
OperationContext operationContext = stub._getServiceClient().getLastOperationContext();
if (operationContext != null) {
MessageContext outMsgContext = operationContext.getMessageContext("Out");
if (outMsgContext != null) {
System.out.println("Out SOAP Message : "+outMsgContext.getEnvelope().toString());
}
}
For incoming messages:
OperationContext operationContext = stub._getServiceClient().getLastOperationContext();
if (operationContext != null) {
MessageContext inMsgContext = operationContext.getMessageContext("In");
if (inMsgContext != null) {
System.out.println("Received SOAP Message: "+ inMsgContext.getEnvelope().toString());
}
}

return login success from a web api to an mvc 4 application

my colleague and myself are working on an application form with login functionality the user logs in from the mvc 4 app and there details are submitted to the web api to be checked against the values held in the database once verified the web api returns a loginResult class that contains the error message (if any) and a bool for stating whether it has been successful or not.
at the mvc 4 application level the code below is used to submit the login details to the web api:
Login Action
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(AccountViewModel model)
{
if (!ModelState.IsValid) return View("Login", model);
await _client.PostAsJsonAsync("api/Applicant/CheckApplicant", model)
.ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode());
var service = DependencyResolver.Current.GetService<IApplyService>();
var loginResult = service.GetLoginResult();
var loginSuccess = loginResult.LoginSuccess;
if (loginSuccess != null && (bool) loginSuccess)
{
FormsAuthentication.SetAuthCookie(model.Email, model.RememberMe);
return RedirectToRoute("Terms And Conditions");
}
return View("Login");
}
the login details are then received at the web api in this method:
Check Applicant Method
public String CheckApplicant(Applicant applicant)
{
Int32 passwordFailureTimeoutMins = Convert.ToInt32(System.Configuration.ConfigurationSettings.AppSettings["PasswordFailureTimeoutMins"]);
Int32 passwordFailureAttempts = Convert.ToInt32(System.Configuration.ConfigurationSettings.AppSettings["PasswordFailureAttempts"]);
ApplicantRepository applicantRepository = new ApplicantRepository();
Applicant applicantDB = applicantRepository.GetById(applicant.Email);
LoginResult loginResult = new LoginResult();
PasswordHelper passwordHelper = new PasswordHelper();
if (applicantDB == null)
{
loginResult.LoginSuccess = false;
loginResult.LoginError = "Your password or login may not be correct.";
}
else
{
bool loginFailureCheck;
if (applicantDB.LoginFailureCount > passwordFailureAttempts)
{
System.TimeSpan diffResult = DateTime.Now.Subtract(Convert.ToDateTime(applicantDB.LastLoginFailure));
if (diffResult.Minutes < passwordFailureTimeoutMins)
{
loginFailureCheck = false;
}
else
{
loginFailureCheck = true;
}
}
else
{
loginFailureCheck = true;
}
if (passwordHelper.CheckPassword(applicant.Password, applicantDB.Password))
{
if(loginFailureCheck)
{
if(applicantDB.AccountActive)
{
loginResult.LoginSuccess = true;
loginResult.LoginError = "Login Successful.";
applicantDB.LastLoginFailure = null;
applicantDB.LastLoginSuccess = DateTime.Now;
applicantDB.LoginFailureCount = 0;
applicantRepository.Update(applicantDB);
}
else
{
loginResult.LoginSuccess = false;
loginResult.LoginError = "This account has been permanently banned.";
}
}
else
{
loginResult.LoginSuccess = false;
loginResult.LoginError = "This account is now temporarily disabled please wait " + passwordFailureTimeoutMins + " minutes before trying again";
applicantDB.LastLoginFailure = DateTime.Now;
applicantDB.LoginFailureCount = applicantDB.LoginFailureCount + 1;
applicantRepository.Update(applicantDB);
}
}
else
{
loginResult.LoginSuccess = false;
loginResult.LoginError = "Your password or login may not be correct.";
applicantDB.LastLoginFailure = DateTime.Now;
applicantDB.LoginFailureCount = applicantDB.LoginFailureCount + 1;
applicantRepository.Update(applicantDB);
}
}
return JsonConvert.SerializeObject(loginResult);
}
as you can see it returns a JsonConvert.SerializeObject(loginResult).
when this is done the process returns to the Login ActionResult as above it then moves to the GetLoginResult() method as shown below:
GetLoginResult
public LoginResult GetLoginResult()
{
const string uri = "http://localhost:55830/api/Applicant/CheckApplicant";
using (var httpClient = new HttpClient())
{
var response = httpClient.GetStringAsync(uri);
return JsonConvert.DeserializeObject<LoginResult>(response.Result);
}
}
when it get to this point it returns an error 405 method not allowed.
How do I consume the loginResult at the mvc 4 app level and what is the best way of sending the loginResult from the web api?
Any advice would be greatly appreciated.
Not sure what exactly you are trying to do but are you making a GET to read the result of the previous POST? You can read the response message of POST to get the result, like this.
public async Task<ActionResult> Login(AccountViewModel model)
{
if (!ModelState.IsValid) return View("Login", model);
var message = await _client.PostAsJsonAsync
("api/Applicant/CheckApplicant", model);
message.EnsureSuccessStatusCode();
LoginResult result = await message.Content.ReadAsAsync<LoginResult>();
// do other stuff here
}
Change the web API action method to return LoginResult directly. The framework will serialize it for you.
public LoginResult CheckApplicant(Applicant applicant)
{
}